Utworzenie dynamicznego łańcucha znaków w C

0

Cześć
Pierwszy raz musiałem pisać kod w C zamiast C++ i przeszkodą okazało się dla mnie zrobienie dynamicznego łańcucha znaków.
Inicjuję zmienną:

char* crf;

Do której następnie chce wprowadzić pewne znaki z klawiatury. Ilość wprowadzonych znaków ma być różna(zależnie od tego ile użytkownik wprowadzi). Czy ktoś mógłby wyjaśnić jak to zrobić by móc wczytać poprawnie taki łańcuch za pomocą metody

scanf_s

? Próbowałem na wiele sposobów - nieskutecznie.
Bardzo proszę o pomoc

2

Musisz utworzyć bufor na tyle duży, żeby pomieścił maksymalną liczbę jaką akceptujesz, a potem ewentualnie możesz go zmniejszyć.

1
DarkFerret napisał(a):

? Próbowałem na wiele sposobów - nieskutecznie.

Pokaż najlepszą próbę, a wyjaśnimy na czym polega problem.

0

To jest moja aktualna wersja:

char* crf="20";
int l;
char temp[10];
scanf_s("%s", temp);
l = strlen(temp);
crf = (char*)malloc(sizeof(char) * l);
strcpy_s(crf,l, temp);

Program się kompiluje, bo wpisaniu wartości się wywala

0

@MarekR22: Oczywiście.To jest moja aktualna wersja:

char* crf="20";
int l;
char temp[10];
scanf_s("%s", temp);
l = strlen(temp);
crf = (char*)malloc(sizeof(char) * l);
strcpy_s(crf,l, temp);

Program się kompiluje, bo wpisaniu wartości się wywala

3
crf = (char*)malloc(sizeof(char) * l);

zapomniałeś o kończącym zerze. Czyli powinno być:

crf = (char*)malloc(sizeof(char) * (l + 1));

A jeszcze lepiej:

char* crf;
char temp[10];
// scanf_s("%9s", temp); // to było źle
scanf("%9s", temp); // albo: scanf_s("%9s", temp, (unsigned)_countof(temp));
crf = strdup(temp);

Edit: wyjaśnienie dodatkowej poprawki:
scanf_s, _scanf_s_l, wscanf_s, _wscanf_s_l | Microsoft Docs

Unlike scanf and wscanf, scanf_s and wscanf_s require you to specify buffer sizes for some parameters. Specify the sizes for all c, C, s, S, or string control set [] parameters. The buffer size in characters is passed as an additional parameter. It immediately follows the pointer to the buffer or variable. For example, if you're reading a string, the buffer size for that string is passed as follows:

char s[10];
scanf_s("%9s", s, (unsigned)_countof(s)); // buffer size is 10, width specification is 9
2
char *input_line_And_And_And() // nazwa specjalnie dla @AnyKtokolwiek 
{
    char buffer[100];
    scanf("%99[^\n]",buffer);
    return strdup(buffer); 
}
char *my_strdup_And_And_And(const char *src) // nazwa specjalnie dla @AnyKtokolwiek 
{
    int size=strlen(src)+1;
    char *buffer=(char*)malloc(size);
    memcpy(buffer,src,size);
    return buffer; 
}

napis dowolnej długości:

#include <stdlib.h>
#include <string.h>
#include <mem.h>

char *read_line(int size,char separator)
{
	char format[32];
	sprintf(format," %%%d[^%c]",size,separator);
	char *bufor=(char*)malloc(size+1);
	scanf(format,bufor);
	return realloc(bufor,strlen(bufor)+1);
}


int main(int n)
{
	char *tmp=read_line(16,'\n');
	printf("%s",tmp);
	free(tmp);
	return 0;
}

Pamiętać że należy zwolnić

0

A czy strdup na pewno należy do C ?

0

@MarekR22: Zamiana na:

crf = (char*)malloc(sizeof(char) * (l + 1));

Nic nie zmieniła niestety

0
DarkFerret napisał(a):

Nic nie zmieniła niestety

Ponieważ @MarekR22 zatrzymał się na pierwszym znalezionym błedzie.
Zaś w podanym kodzie dalej próbujesz wepchnąć hipotetycznie 9 wczytanych znaków (plus znak końca) wcisnąć w 3 znaki.
Oczywiście 9+1 o ile użyszkodnik złośliwie nie poda więcej, wtedy mażesz po pamięci jeszcze w scanf'ie

0

@_13th_Dragon: Visual studio rozkazuje zamienic scanf i sprintf na scanf_s i sprintf_s, ale nie powinno to chyba mieć wpływu. No ale niestety również wywala

0

Co wywala? Sądzę że niepoprawnie używasz. Szklana kula wskazuje na błąd w 42 wierszu.

0

@_13th_Dragon: Wybacz nieścisłość. Nie wklejałem kodu bo jest praktycznie ten który Ty wysłałeś. Program uruchamia się ale kończy się po chwili wyrzucając kod błędu jeszcze przed wpisaniem wartości.

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
//#include <mem.h> --Visual studio nie znajduje tej biblioteki

char* read_line(int size, char separator)
{
    char format[32];
    sprintf_s(format, " %%%d[^%c]", size, separator); //Debuger w tym miejscu zgłasza wyjątek
    char* bufor = (char*)malloc(size + 1);
    scanf_s(format, bufor);
    return realloc(bufor, strlen(bufor) + 1);
}

int main(int n)
{
    char* tmp = read_line(16, '\n');
    printf("%s", tmp);
    free(tmp);
    return 0;
}
0

przewróć z powrotem sprintf i scanf oraz dodaj:
#pragma warning(suppress : 4996).
lub użyj jakiegoś kompilatora zgodnego z obowiązującym standardem.

3

@DarkFerret:

DarkFerret napisał(a):

A czy strdup na pewno należy do C ?

strdup pochodzi ze standardu POSIX - https://pubs.opengroup.org/onlinepubs/9699919799/functions/strdup.html
W książce którą powinieneś przeczytać jest treść tej funkcji:

char *strdup(char *s)
{
	char *p;
	/* tworzy kopię s */
	p = (char *) malloc(strlen(s)+1); /* +1 dla '\0' */
	if (p != NULL)
		strcpy(p, s);
	return p;
}

0

@_13th_Dragon: Dziękuję za pomoc :) Zrobiłem tak jak powiedziałeś, zamieniłem z powrotem na sprintf i scanf. Konieczne było jeszcze dodanie definicji preprocesora: _CRT_SECURE_NO_WARNINGS. Wszystko działa ;) Bardzo dziękuję za odpowiedzi

1 użytkowników online, w tym zalogowanych: 0, gości: 1