Jak odczytywać nieograniczoną liczbę znaków do zmiennej char*
bez określania rozmiaru?Jak odczytać nieograniczoną liczbę znaków w C
Załóżmy na przykład, że chcę przeczytać adres pracownika, który może również przyjąć wiele wierszy.
Jak odczytywać nieograniczoną liczbę znaków do zmiennej char*
bez określania rozmiaru?Jak odczytać nieograniczoną liczbę znaków w C
Załóżmy na przykład, że chcę przeczytać adres pracownika, który może również przyjąć wiele wierszy.
Musisz zacząć od "zgadywania" rozmiaru, jakiego się spodziewałeś, a następnie przydzielić bufor o dużej wartości, używając malloc
. Jeśli okaże się to zbyt małe, użyjesz realloc
, aby zmienić rozmiar bufora na nieco większy. Przykładowy kod:
char *buffer;
size_t num_read;
size_t buffer_size;
buffer_size = 100;
buffer = malloc(buffer_size);
num_read = 0;
while (!finished_reading()) {
char c = getchar();
if (num_read >= buffer_size) {
char *new_buffer;
buffer_size *= 2; // try a buffer that's twice as big as before
new_buffer = realloc(buffer, buffer_size);
if (new_buffer == NULL) {
free(buffer);
/* Abort - out of memory */
}
buffer = new_buffer;
}
buffer[num_read] = c;
num_read++;
}
Jest tuż przy mojej głowie, a może (czytaj: będzie prawdopodobnie) zawierają błędy, ale powinny dać dobry pomysł.
@Codeka - powinieneś unikać 'x = realloc (x, newsize);' Jeśli realloc się nie powiedzie, stracisz oryginalny wskaźnik i stracisz pamięć. To powiedziawszy, jeden wyjątek od tej zasady jest w porządku, jeśli twoja polityka na niepowodzenie przydziału ma zakończyć proces. –
Ale, uwaga ... jeśli realloc nie powiedzie się, wyciekłeś poprzedni wskaźnik bufora. Należy zrobić coś takiego, jak "void * sav = ptr; if ((ptr = realloc (ptr, newsiz)) == null) {free (sav); } ' –
Dzięki chłopaki, to prawda. Zaktualizuję mój przykład ... minęło trochę czasu odkąd użyłem prostego C :) –
Co powiesz na umieszczenie bufora 1KB (lub 4KB) na stosie, czytanie do tego, aż znajdziesz koniec adresu, a następnie przydzielisz bufor o odpowiednim rozmiarze i skopiujesz do niego dane? Po powrocie z funkcji bufor stosu znika i masz tylko jedno połączenie z malloc
.
Co się dzieje, gdy adres jest większy niż bufor 1k lub 4k na stosie? – Gabe
@gabe: Jak piszesz adres 4KB na kopercie? – tomlogic
Brak znajomości rozmiaru ciągu wejściowego i próba odczytania go w buforze o stałym rozmiarze jest źródłem niezapowiedzianych problemów bezpieczeństwa w kodzie C. – Gabe
Wystarczyło odpowiedzieć Ex 7.1, str. 330 z C, autor: Ivor Horton, wydanie trzecie. Zajęło mu to kilka tygodni. Umożliwia wprowadzanie liczb zmiennoprzecinkowych bez wcześniejszego określenia liczby liczb wprowadzonych przez użytkownika. Przechowuje liczby w tablicy dynamicznej, a następnie wypisuje liczby i średnią wartość. Używanie Code :: Blocks z Ubuntu 11.04. Mam nadzieję, że to pomoże.
/*realloc_for_averaging_value_of_floats_fri14Sept2012_16:30 */
#include <stdio.h>
#include <stdlib.h>
#define TRUE 1
int main(int argc, char ** argv[])
{
float input = 0;
int count=0, n = 0;
float *numbers = NULL;
float *more_numbers;
float sum = 0.0;
while (TRUE)
{
do
{
printf("Enter an floating point value (0 to end): ");
scanf("%f", &input);
count++;
more_numbers = (float*) realloc(numbers, count * sizeof(float));
if (more_numbers != NULL)
{
numbers = more_numbers;
numbers[count - 1] = input;
}
else
{
free(numbers);
puts("Error (re)allocating memory");
exit(TRUE);
}
} while (input != 0);
printf("Numbers entered: ");
while(n < count)
{
printf("%f ", numbers[n]); /* n is always less than count.*/
n++;
}
/*need n++ otherwise loops forever*/
n = 0;
while(n < count)
{
sum += numbers[n]; /*Add numbers together*/
n++;
}
/* Divide sum/count = average.*/
printf("\n Average of floats = %f \n", sum/(count - 1));
}
return 0;
}
/* Success Fri Sept 14 13:29 . That was hard work.*/
/* Always looks simple when working.*/
/* Next step is to use a function to work out the average.*/
/*Anonymous on July 04, 2012*/
/* http://www.careercup.com/question?id=14193663 */
Dobra próba! Kilka sugestii dotyczących wydajności - staraj się unikać wielu realloc, które obejmują kopiowanie wszystkiego dookoła. Zamiast tego prześlij ponownie 2 lub 4 razy i zliczaj zarówno dostępną przestrzeń, jak i wykorzystaną przestrzeń. Również średnia może być obliczona w czasie wykonywania bez uprzedniego zapisywania czegokolwiek. – qdot
Poniższe odpowiedzi demonstrują mechanikę problemu i zachęcam do ich przestudiowania. Jedną z powszechnych implementacji jest 'getline'. – dmckee
Musisz zacząć od upewnienia się, że twój sprzęt ma nieograniczoną pamięć! – theglauber