How to clear buffer after reading an input in c? - c

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void generarDimension(int, void **, int);
void reallocarDimensiones(int, void **, int);
void preguntarValor(int *);
char *generarCadena(char *);
typedef struct listaAlu{//this is a list of students
char cedula[7];//this means id
char *nombreApellido;//this means name and lastname
short curso;//this means the year of the student in college/school
unsigned short anho;//and this means year-E.g: 2017
};
int main(void){
struct listaAlu *alu = NULL;
int salir=1;
char c;
unsigned int cont = 0;
unsigned int i;
size_t size = 0;
struct listaAlu *temp = NULL;
while(salir!=0){//Condition until user press exit option
printf("Agregar Alumno?Ingrese 1 para Agregar, y 0 para salir\n");//This means "Add student?Press 1 to add, and 0 to exit
preguntarValor(&salir);//this verifies user input
if(salir==1){//if user adds then it asks info of the student
cont++;
if ( NULL == ( temp = realloc ( alu, size + 2))) {//realloc for each character input and '\0'
fprintf ( stderr, "realloc problem\n");
}//this is for increasing the number of students
alu = temp;
printf("Ingrese Cedula:\n");//This means "Enter id"
scanf("%s", &(alu+(size))->cedula);
printf("Ingrese Nombre y Apellido:\n");//This means "Enter name and lastname"
(alu+(size))->nombreApellido = generarCadena((alu+(size))->nombreApellido);
printf("Ingrese Curso:\n");//This means enter college/school year
scanf("%hd", &(alu+(size))->curso);
printf("Ingrese Anho:\n");//and this means "Enter year"
scanf("%hd", &(alu+(size))->anho);
size++;
}
}
for(i=0;i<cont;i++){
printf("\tAlumno %d\n", i+1);
printf("Nombre:\t%s\n", (alu+i)->nombreApellido);
printf("Cedula:\t%s\n", (alu+i)->cedula);
printf("Curso:\t%d\n", (alu+i)->curso);
printf("Anho:\t%d\n", (alu+i)->anho);
}//This prints Everything the user entered
free(alu);
return 0;
}//Sorry for writing my program entirely on the main >.<
void generarDimension(int bloques, void **ptr, int tamanho){
void **ptrAux;
*ptrAux = malloc(bloques * tamanho);
if(*ptrAux==NULL){
printf("No se pudo almacenar memoria\n");
}else{
*ptr = *ptrAux;
free(ptrAux);
}
}//this I didn't use, but it is for generating an array through a pointer
void reallocarDimensiones(int bloques, void **ptr, int tamanho){
void **ptrAux;
*ptrAux = realloc(*ptr,bloques * tamanho);
if(*ptrAux==NULL){
printf("No se pudo almacenar memoria\n");
}else{
*ptr = *ptrAux;
free(ptrAux);
}
}//This I didn't either, but it is for reallocating any given pointer
void preguntarValor(int *n){
long entero, lector;
*n=-2;
do{
printf("\nSi ingresa otro numero o caracter, vuelva a ingresar opcion\n");
while(!scanf("%d", &entero)){
while((lector=getchar()) !='\n' && lector !=EOF );
}
*n=entero;
}while(*n>1 || *n<0);//You can change this parameters according to the numbers you want
}//This subrutine scans only integers between 1 and 0
char *generarCadena(char *scaneado){
char *temp = NULL;
int in = 0;
size_t size = 0;
while ( '\n' != ( in = getchar ( ))) {//loop until newline
if ( NULL == ( temp = realloc ( scaneado, size + 2))) {//realloc for each character input and '\0'
fprintf ( stderr, "realloc problem\n");
return scaneado;
}
scaneado = temp;
scaneado[size] = in;//set input
scaneado[size + 1] = '\0';//terminate
size++;
}
return scaneado;
}//This subrutine is for geting an input of chars of any given length
This is a program to store a college/school student list, I want to know how to improve this code, however in the part where I ask the user to enter strings, on the second one I can't enter anything. And if I try to enter more than 2 students, my code doesn't print all the info of the students I entered

struct listaAlu *temp = NULL;
temp = realloc ( alu, size + 2);//<- wrong size
realloc(alu, size + 2) will allocate only 2 bytes in the first run. But you need much more than that. The total size needed is number of elements in the array multiply by the size of the structure. That is sizeof(struct listaAlu) which is about 15 bytes.
realloc( alu, sizeof(struct listaAlu) * (size + 1) );
You don't need to increment the size by 2.
Make sure to check the input at the right places. Clear the input when scanf fails.
To get first name and last name, you can use fgets and strdup
There are major problems with generarDimension and reallocarDimensiones. You may want to leave those out.
struct listaAlu{
char cedula[7];//this means id
char *nombreApellido;//this means name and lastname
short curso;//this means the year of the student in college/school
unsigned short anho;//and this means year-E.g: 2017
};
void clear()
{
int c;
while((c = getchar()) != '\n' && c != EOF);
}
int main(void)
{
struct listaAlu *alu = NULL;
size_t size = 0;
while(1)
{
alu = realloc( alu, sizeof(struct listaAlu) * (size + 1) );
if (!alu)
{
fprintf(stderr, "realloc problem\n");
break;
}
char buf[256] = { 0 };
printf("Enter id:\n");
fgets(buf, sizeof(buf), stdin);
buf[strcspn(buf, "\r\n")] = 0;
buf[sizeof(alu[size].cedula) - 1] = 0;
strcpy(alu[size].cedula, buf);
printf("Enter name and lastname:\n");
fgets(buf, sizeof(buf), stdin);
buf[strcspn(buf, "\r\n")] = 0;
alu[size].nombreApellido = _strdup(buf);
for(;;)
{
printf("Enter college/school year:\n");
if (scanf("%hd", &alu[size].curso) == 1)
break;
printf("input error\n");
clear();
}
for(;;)
{
printf("Enter year:\n");
if (scanf("%hd", &alu[size].anho) == 1)
break;
printf("input error\n");
clear();
}
size++;
printf("Press 1 to continue\n");
char input;
scanf(" %c", &input);
if(input != '1')
break;
clear();
}
for(size_t i = 0; i < size; i++)
{
printf("Alumno %d\n", i);
printf("Nombre:\t%s\n", alu[i].nombreApellido);
printf("Cedula:\t%s\n", alu[i].cedula);
printf("Curso:\t%hd\n", alu[i].curso);
printf("Anho:\t%hd\n", alu[i].anho);
}
for(size_t i = 0; i < size; i++)
free(alu[i].nombreApellido);
free(alu);
return 0;
}
Edit
realloc does not need to be wrapped in a different function. But for fun purposes, you can do the following:
void* my_realloc1(void *ptr, int size)
{
ptr = realloc(ptr, size);
if (!ptr) printf("error\n");
return ptr;
}
//usage:
alu = my_realloc1(alu, sizeof(struct listaAlu) * (size + 1));
if (!alu) printf("error\n");
my_realloc1 will work here, however nothing is gained. This is just extra lines of code. It's easier and more clear to use realloc directly and do the necessary error handling.
Another method is to pass a reference:
void my_realloc2(void **ptr, int size)
{
*ptr = realloc(*ptr, size);
}
//usage: (*** Note the address `&` operator ***)
my_realloc2(&alu, sizeof(struct listaAlu) * (size + 1));
if (!alu) printf("error\n");
Again this will work, but it just adds more code.
The function generarCadena seems okay. You could simplify as follows:
char *my_getline()
{
char *buf = NULL;
int in = 0;
size_t size = 0;
while('\n' != (in = getchar()))
{
size++;
buf = realloc(buf, size);
buf[size - 1] = (char)in;
}
size++;
buf = realloc(buf, size);
buf[size - 1] = 0;
return buf;
}
//usage:
printf("Enter name and lastname:\n");
alu[size].nombreApellido = my_getline();
And use scanf for to read 6 characters (because size of cedula is 7)
printf("Enter 6 characters:\n");
scanf("%6s", alu[size].cedula);
alu[size].cedula[6] = '\0';
clear();
To be safe, make sure the input is null terminated, and clear the buffer.
Or you can use fgets as I used in the example. This will read up to 256 characters:
char buf[256];
fgets(buf, sizeof(buf), stdin);
fgets is sometimes easier because you don't need to clear the buffer. But buf includes end of line character \n, you have to remove \n in this case.

Related

Confusion on Malloc behavior, why it last input is not taken?

This is a snippet of a program I am working on. I wanted to get information from the user, where the target variable cannot have predefined memory. For some reason my function does not work for the last section of the code. Any help will be appreciated.
Current Output:
Enter your name: Daniel
Hi Danie (expected as I put the limit to 5 characters)
Enter your phone number: 123456789
123456789
Enter your Note: (Here it breaks and does not print the contactNote variable.)
Here is the code:
char *getwords(int numberoftimes) {
char *words = malloc(sizeof(char));
int index = 0;
int character = EOF;
int size = 0;
int increase = 1;
int counter = 0;
char *temp;
while (character) {
character = getc(stdin);
if (numberoftimes == 0) {
if (character == '\n') {
character = 0;
}
} else if (counter == numberoftimes || character == '\n') {
character = 0;
}
if (size <= index) {
size += increase;
temp = realloc(words, size);
if (!temp) {
free(words);
words = NULL;
break;
}
words = temp;
}
words[index++] = character;
counter++;
}
return words;
}
int main() {
char *contactName, *contactNote;
long contactNumber;
printf("\nEnter your name: ");
char *getwords();
char *Name = getwords(5);
printf("\nHi %s\n", Name);
printf("\nEnter your phone number: ");
scanf("%lu", &contactNumber);
printf("\n%lu\n", contactNumber);
printf("\nEnter your Note: ");
char *getwords();
char *Note = getwords(0);
printf("\n%s\n", Note);
}
scanf() for the contact number leaves the ENTER sitting in the [keyboard] input buffer.
int main() {
char *contactName, *contactNote; // unused variables
long contactNumber;
printf("\nEnter your name: ");
char* getwords(); // unnecessary function declaration
char *Name = getwords(5);
printf("\nHi %s\n", Name);
printf("\nEnter your phone number: ");
scanf("%lu", &contactNumber); // leaves <ENTER> in buffer
printf("\n%lu\n", contactNumber);
printf("\nEnter your Note: ");
char* getwords(); // unnecessary function declaration
char *Note = getwords(0); // empty line because of previous <ENTER>
printf("\n%s\n", Note);
}
I suggest you also use getwords() for the number, then convert to long with strtol().
There are multiple problems in your code:
mixing getc() and scanf() is tricky as scanf() leaves the trailing newline pending in stdin so getc() reads this newline immediately. You should read all of your inputs with getwords().
the extra char *getwords(); declarations inside the body of main() are redundant and confusing.
getwords() is too complicated, especially for exiting the loop.
you do not always check for memory allocation error.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
char *getwords(const char *prompt, int maxlen) {
char *words = malloc(sizeof(char));
int index = 0;
int size = 0;
char *temp;
if (words == NULL)
return NULL;
printf("%s", prompt);
for (;;) {
int character = getc(stdin);
if (character == EOF || character == '\n')
break;
if (index < maxlen) {
if (index >= size) {
size += 1;
temp = realloc(words, size + 1);
if (!temp) {
free(words);
return NULL;
}
words = temp;
}
words[index++] = character;
}
}
words[index] = '\0';
return words;
}
int main() {
char *Name = getwords("\nEnter your name: ", 5);
if (!Name)
return 1;
printf("\nHi %s\n", Name);
char *contact = getwords("\nEnter your phone number: ", 20);
if (!contact)
return 1;
long contactNumber = 0;
sscanf(contact, "%lu", &contactNumber);
printf("\n%lu\n", contactNumber);
char *Note = getwords("\nEnter your Note: ", 10);
if (!Note)
return 1;
printf("\n%s\n", Note);
return 0;
}

C Program - Error Combine String Array into Program

I'm trying to write program to ask user to enter First and Last Name. Then my program will result their Full Name (combined First + Last Name) and the length of their Full Name. My Output right now does empty Full Name and 0 length. I guess my problem is at display_name functions. Here is my code so far. Thank you.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void display_name(char *fullname);
int count_char( char*x_ptr);
char * get_name(char * first_name, char * last_name);
#define MAX 80 // maximum number of array elements
int main(void)
{
char first_name[MAX];
char last_name[MAX];
char *x_ptr;
system("cls");
printf("Enter Last Name: \n" );
scanf("%s", &last_name );
printf("Enter First Name: \n" );
scanf("%s", &first_name );
x_ptr = get_name(first_name, last_name);
display_name(x_ptr);
puts("");
system("pause");
return 0;
}
char * get_name(char *first_name, char *last_name)
{
static char fullname[MAX];
char x;
x = 0;
strcpy(fullname, first_name);
strcat(fullname, " ");
strcat(fullname, last_name);
while (((fullname[x] = getchar()) != '\n') && (x < (MAX-1)))
{
x++;
}
fullname[x] = '\0';
return(fullname);
}
/* Function to print out string passed to it and display the length of fullname*/
void display_name(char *fullname)
{
char *a;
printf("Your Full name is ");
a = &fullname[0];
while (*a != '\0')
{
putchar(*a);
a++;
}
int length;
length = strlen(fullname);
printf("\nHas %d Characters", length);
length = count_char(fullname);
printf("\nHas %d Non Space Characters", length);
}
/* function to return count of non space characters*/
int count_char( char * x_ptr)
{
char *b;
unsigned int count=0;
b = x_ptr;
while (*b != '\0')
{
if (*b != ' ')
count++;
b++;
}
return
(count);
}
scanf("%s", &last_name );
Compiler complained and you ignored it. It should be scanf("%s", last_name );. Same goes with firstname. Yours had type char (*)[] and scanf expects char* which is what we gave in second case.
This part is doing nothing that you would do to achieve what you are trying to do.
while (((fullname[x] = getchar()) != '\n') && (x < (MAX-1)))
This is using getchar to get the characters from stdin and put it in the char array where you are storing the concatenated name.
Using static char array is not a good solution. The next time you try to use this function - it will overwrite the data previously written by another function. Illustration implementation of the function get_name would be
char * get_name(char *first_name, char *last_name)
{
char *fullname = malloc(strlen(first_name)+2+strlen(last_name));
if(!fullname){
perror("malloc");
exit(EXIT_FAILURE);
}
strcpy(fullname, first_name);
strcat(fullname, " ");
strcat(fullname, last_name);
return fullname;
}
Benefit of using this implementation is that - now the data that is being used is not closely coupled with the methods that call this one. So it can be reused independent of it's previous usage in another function.
Also when using the function get_name remember to free the dynamically allocated memory when you are done working with it.

Adding structs to an array in C

I am having a problem in adding structs to an array in C-language. I think it's stemming from the fact that I might not be using correctly the pointers.
I have some struct with the following syntax:
struct account
{
int num;
char* fname;
char* lname;
char* pin;
double bal;
};
and in my main function I want to have a for loop that adds a struct to an array after going through and setting the variables of my struct to something. This is my full code so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct account
{
int num;
char* fname;
char* lname;
char* pin;
double bal;
};
void split_str (struct account *a,char *line)
{
int i = 0; //incrementer to tell what we are looking at: num, fname, lname, pin, or bal
int acc_num; //temp vals to store acc_num casting and balance casting
double bal;
char * str;
str = strtok(line, " ");
while (str!= NULL){
switch(i){
case 0:
acc_num = atoi(str);
a->num = acc_num;
acc_num = 0;
break;
case 1:
a->fname = str;
break;
case 2:
a->lname = str;
break;
case 3:
a->pin = str;
break;
case 4:
bal = atof(str);
a->bal = bal;
bal = 0;
break;
}
str = strtok (NULL, " ");
i++; //increment because we want to look through all 5 possibilities of vars
}
}
int main()
{
FILE *fh = fopen("account_info.txt", "r");
struct account accts[100];
if (fh != NULL)
{
char line[256];
for (int i=0; fgets(line, sizeof line, fh) != NULL; i++)
{
split_str(&accts[i], line);
}
}
fclose(fh);
for (int i=0; i<3; i++)
{
printf("%s %s index: %i\n", accts[i].fname, accts[i].lname, i);
}
}
This code is used with an account_info.txt file. All that file contains is one "account" per line delimited with a space " " char. Example:
123456 Jane Doe 1234 250.50
123457 John Smith 2222 12.34
123458 Sally Jones 9999 321.79
The problem with my current code is that it does seem to enter a struct in to the array, but it does it incorrectly. Here is what my code spits out at me when I run it with the print statement in the second for loop of my code:
Sally Jones index: 0
Sally index: 1
Sally Jones index: 2
Any help at all for why this is acting this way would be much appreciated.
In split_str() you are assigning pointers (locations) to
the local strings in the accounts that are dangling after
the function has been left (because the str pointer in
split_str is de-allocated and possibly reused at any
other point in the code later on...).
The make sure that the information gathered in the
split_str survives the function calls, you need
to allocate memory to fname (or lname or pin or any
other pointer) in the function, and then use some memcpy
or other methods to copy the information that str is pointing
to into the structure pointed to by a.
The problem is that there is only one instance of line in main so all the array pointers are pointing to that one line and whatever it contains after the last fgets.
sscanf could be used to parse the integer and double. Using the %n specifier, the starting and stopping indexes for names and pin can be captured. The %*s specifier will read and discard the strings as their length is not yet known. Once the start and stop indexes are known, memory can be allocated and the strings copied using memcpy.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct account
{
int num;
char* fname;
char* lname;
char* pin;
double bal;
};
int split_str (struct account *a,char *line)
{
int startfn = 0;
int stopfn = 0;
int startln = 0;
int stopln = 0;
int startpin = 0;
int stoppin = 0;
if ( ( 2 == sscanf ( line, "%d %n%*s%n %n%*s%n %n%*s%n %lf"
, &(a->num)
, &startfn
, &stopfn
, &startln
, &stopln
, &startpin
, &stoppin
, &(a->bal)))) {
if ( ( a->fname = malloc ( ( stopfn - startfn) + 1)) == NULL) {
fprintf ( stderr, "problem malloc\n");
exit ( 1);
}
memcpy ( a->fname, &line[startfn], stopfn - startfn);
a->fname[stopfn - startfn] = '\0';
if ( ( a->lname = malloc ( ( stopln - startln) + 1)) == NULL) {
fprintf ( stderr, "problem malloc\n");
exit ( 1);
}
memcpy ( a->lname, &line[startln], stopln - startln);
a->lname[stopln - startln] = '\0';
if ( ( a->pin = malloc ( ( stoppin - startpin) + 1)) == NULL) {
fprintf ( stderr, "problem malloc\n");
exit ( 1);
}
memcpy ( a->pin, &line[startpin], stoppin - startpin);
a->pin[stoppin - startpin] = '\0';
return 1;
}
return 0;
}
int main()
{
FILE *fh = fopen("account_info.txt", "r");
struct account accts[100];
int loaded = 0;
if (fh != NULL)
{
char line[256];
for (int i=0; fgets(line, sizeof line, fh) != NULL; i++)
{
if ( split_str(&accts[i], line)) {
loaded++;
}
}
}
fclose(fh);
for (int i=0; i<loaded; i++)
{
printf("%s %s index: %i\n", accts[i].fname, accts[i].lname, i);
}
for (int i=0; i<loaded; i++)//free allocated memory
{
free ( accts[i].fname);
free ( accts[i].lname);
free ( accts[i].pin);
}
}

Printing strings from 2D array using pointer to pointer

I am trying to build a program that uses dynamic allocation to build an array of strings.
After the user finishes to enter the words he wants into the array i want to print the array one word after the other. I am using pointers to pointers, however it doesn't seem to work:
#define SIZE 256
void paintWords(char **words, int count_words);
void main() {
char **words = NULL;
int flag = 1;
char buffer[SIZE];
int count_words = 0;
char *curr_word;
while (flag)
{
_flushall();
printf("Enter a word:");
gets(buffer);
words = (char**)realloc(words,++count_words*sizeof(char*));
curr_word = (char*)malloc(strlen(buffer) + 1);
words[count_words - 1] = curr_word;
printf("Do you wish to continue(0-no, 1-yes):");
scanf("%d", &flag);
}
paintWords(words, count_words);
}
void paintWords(char **words, int count_words) {
int j = 0;
for (int i = 0; i < count_words; i++)
{
printf("%s\n", words[i][j]);
}
}
Copy buffer to your malloc'ed block with strcpy
strcpy(curr_word, buffer);
you are discarding the read word since you don't put it anywhere
Don't use gets use fgets instead
fgets(buffer, sizeof(buffer), stdin);
this would prevent a buffer overflow.
This is just the jst which in your case is the 0th character of the word
printf("%s\n", words[i][j]);
change it to
printf("%s\n", words[i]);
turn compiler warnings on, it would tell you about printf expecting a char * and recieving char instead.
Also consider the following:
main() should return int.
You don't need to cast malloc.
Don't overwrite your pointer with realloc, use a temporary pointer and assign it to array on success only. Otherwise if realloc returns NULL you will not be able to free(array) for example.
++count_words
words = realloc(words,count_words*sizeof(char*));
words[count_words-1] = malloc(strlen(buffer) + 1);
strcpy(words[count_words-1],buffer);
Later print the array
printf("%s\n",words[i]);
realloc() can fail so
char *temp = realloc(words,count_words*sizeof(char*));
if(temp != NULL)
words = temp;
Few other fixes will be
You shouldn't be using gets which is no more a standard. Use fgets() and note that fgets() comes with a newline character
Check the code below:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define SIZE 256
void paintWords(char **words, int count_words);
void main() {
char **words = NULL,ch;
int flag = 1;
char buffer[SIZE];
int count_words = 0;
//char *curr_word;
while (flag)
{
printf("Enter a word:");
fgets(buffer,sizeof(buffer),stdin);
words = (char**)realloc(words,++count_words*sizeof(char*));
words[count_words - 1] = (char*)malloc(strlen(buffer) + 1);
strcpy(words[count_words-1],buffer);
printf("Do you wish to continue(0-no, 1-yes):");
scanf("%d", &flag);
while((ch = getchar()) != '\n');
}
paintWords(words, count_words);
}
void paintWords(char **words, int count_words) {
int i;
for (i=0; i < count_words; i++)
{
printf("%s", words[i]);
}
}

filling a Char array with scanf in C

How can I fill an empty Char Array with keyboard?
something like
char a_string[];
while("if not Q")
{
printf("Enter a number: ");
scanf("%c", a_string);
}
I know this is wrong
I just want to know how to give values to my a_string[], without limiting the size.
so the size will vary depend on how many keys i'm gonna enter from keyboard.
Thanks!
If you will know at the start of runtime how many keys you'll enter, you can have it ask first for the number of keys and then for the individual characters, as in the untested snippet below.
Otherwise, you have to set some real-world maximum (e.g. 10000) that will never be reached, or, if that's not possible, set a per-array maximum and make provisions for rollover into a new array. That last option really is the same (eventually bounded by memory) but gives you a larger maximum.
char *mychars;
int numchars;
printf("Please enter the total number of characters:\n");
if (scanf("%d", &numchars) == NULL) {
printf("couldn't read the input; exiting\n");
exit(EXIT_FAILURE);
}
if (numchars <= 0) {
printf("this input must be positive; exiting\n");
exit(EXIT_FAILURE);
}
mychars = (char *) malloc (numchars * sizeof(char));
int current_pos = 0;
printf("Enter a digit and hit return:\n");
while (scanf("%c", &mychars[current_pos]) != NULL && current_pos < numchars) {
current_pos++;
printf("Enter a digit and hit return:\n");
}
Try this:
#include <stdlib.h>
#include <stdio.h>
int main() {
char *string = NULL;
char *newstring = NULL;
char c = '\0';
unsigned int count = 0;
while(c != 'Q'){
c = getc(stdin);
if(string == NULL){
string = (char *) malloc(sizeof(char)); // remember to include stdlib.h
string[0] = c;
}
else{
newstring = (char *) realloc(string, sizeof(char)*count);
string = newstring;
string[count] = c;
}
count++;
}
string[count-1] = '\0'; // remove the Q character
fprintf(stderr,"here you are: %s",string);
free(string); // remember this!
return 0;
}
Repetitive calls to realloc() will meet the need.
Double realloc() size as needed to avoid O(n) calls.
char *GetQLessString(void) {
size_t size_alloc = 1;
size_t size_used = size_alloc;
char *a_string = malloc(size_alloc);
if (a_string == NULL) {
return NULL; // Out of memory
}
char ch;
while(scanf("%c", &ch) == 1 && (ch != 'Q')) {
size_used++;
if (size_used > size_alloc) {
if (size_alloc > SIZE_MAX/2) {
free(a_string);
return NULL; // Too big - been typing a long time
}
size_alloc *= 2;
char *new_str = realloc(a_string, size_alloc);
if (new_str == NULL) {
free(a_string);
return NULL; // Out of memory
}
a_string = new_str;
}
a_string[size_used - 2] = ch;
}
a_string[size_used - 1] = '\0';
return a_string;
}
Code could do a final realloc(a_string, size_used) to trim excess memory allocation.
Calling routine needs to call free() when done with the buffer.
The following would be cleaner.
int ch;
while((ch = fgetc(stdin)) != EOF && (ch != 'Q')) {

Resources