my last printf statement is not printing I'm not sure what's wrong since I'm using getchar to read the standard input, I must also use %s for this problem. I'm trying to make the last printf statement print the exact input from standard input.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define INITIAL_BUFFER_SIZE 16
// Input: pointer to the the old_Buffer i.e. *buffer and the pointer to the old_Buffer size i.e. *buffer_size
// Output: pointer to the new_Buffer i.e. *temp
// Summary: Function to increase the buffer size to double whenever the old_Buffer reaches the max possible size
char* IncreaseBuffer(char *buffer,int *buffer_size){
// Creating a new buffer of double the size
int temp_sz = *buffer_size;
temp_sz = 2*temp_sz;
char *temp;
temp = realloc(buffer, temp_sz);
// If the allocation is not successful, then exit the program and print the error
if (!temp) {
printf("Error: Unable to Realloc\n");
exit(EXIT_FAILURE);
}
// Update the buffer size as per the new buffer and return the new buffer instead of the old buffer
*buffer_size = temp_sz;
return temp;
}
int main(void){
// INITIAL BUFFER
char *myString;
myString = malloc(INITIAL_BUFFER_SIZE);
int curr_size = INITIAL_BUFFER_SIZE;
// TEMPORARY CHARACTER TO STORE THE READ CHARACTER
char ch;
printf("Enter a string: ");
// Number of buffer increases
int buff_inc = 0;
// Length of the string
int len = 0;
while((ch=getchar())!=EOF){
if(ch == '\n'){
// If character read is a new line, then we break and assume that we have got our string to print by now
break;
}else{
if(len >= curr_size - 1){
// If length of the string is greater than the buffer size, then we increase the buffer size
// Also increment the number of buffer increases
myString = IncreaseBuffer(myString, &curr_size);
buff_inc++;
}
// Append the read character to the end of the buffer
myString[len++] = ch;
}
}
printf("String size: %d\n", len);
printf("Buffer increases: %d\n", buff_inc);
printf("You entered: %s\n",myString);
return 0;
}
You must not free the old buffer after calling realloc. That is bad. It has already been resized and memory allocation taken care of. It might even keep the same address after reallocation.
Just remove the following lines:
// Free the old buffer
free(buffer);
buffer = NULL;
And, already pointed out in the comments, you forgot to terminate your string. Do this after the loop:
myString[len] = '\0';
Trimmed down after just seeing #paddy's answer, but for the record this is from the realloc docs:
On success, returns the pointer to the beginning of newly allocated memory. The returned pointer must be deallocated with free() or realloc(). The original pointer ptr is invalidated and any access to it is undefined behavior (even if reallocation was in-place).
On failure, returns a null pointer. The original pointer ptr remains valid and may need to be deallocated with free() or realloc().
Related
I have problem reading a file in c and storing in array of strings
char **aLineToMatch;
FILE *file2;
int bufferLength = 255;
char buffer[bufferLength];
int i;
char *testFiles[] = { "L_2005149PL.01002201.xml.html",
"L_2007319PL.01000101.xml.html",
NULL};
char *testStrings[] = { "First",
"Second",
"Third.",
NULL};
file = fopen(testFiles[0], "r"); // loop will come later, thats not the problem
while(fgets(buffer, bufferLength, file2) != NULL) {
printf("%s\n", buffer);
// here should be adding to array of strings (testStrings declared above)
}
fclose(file);
}
and then I do some checks, some prints etc.
for(aLineToMatch=testStrings; *aLineToMatch != NULL; aLineToMatch++) {
printf("String: %s\n", *aLineToMatch);
How to properly change the values of *testFiles[] to include valid values read from file and add NULL at the end?
I think the key issue here is that in C you must manage your own memory, and you need to know the difference between the different types of storage available in C.
Simply put, there's:
Stack
Heap
Static
Here's some relevant links with more detail about this:
https://www.geeksforgeeks.org/memory-layout-of-c-program/
https://craftofcoding.wordpress.com/2015/12/07/memory-in-c-the-stack-the-heap-and-static/
In higher-level languages everything is on the heap anyway so you can pretty much manipulate it however you please.
However, bog-standard arrays and strings in C have static storage of a fixed size.
The rest of this answer is in the code comments below.
I've modified your code and tried to give explanations and context as to why it is needed.
// #Compile gcc read_line_by_line.c && ./a.out
// #Compile gcc read_line_by_line.c && valgrind ./a.out
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdbool.h>
// When declaring an array, the size of the array must be a compile-time constant
// i.e. it cannot be a dynamic variable like this: int n = 3; int numbers[n];
#define BUFFER_SIZE_BYTES 255
// Uses static program storage, size is fixed at time of compilation
char *files[] = {"file1.txt", "file2.txt"}; // The size of this symbol is (sizeof(char*) * 2)
// Hence this line of code is valid even outside the body of a function
// because it doesn't actually execute,
// it just declares some memory that the compiler is supposed to provision in the resulting binary executable
// Divide the total size, by the size of an element, to calculate the number of elements
const int num_files = sizeof(files) / sizeof(files[0]);
int main() {
printf("Program start\n\n");
printf("There are %d files to read.\n", num_files);
// These lines are in the body of a function and they execute at runtime
// This means we are now allocating memory 'on-the-fly' at runtime
int num_lines = 3;
char **lines = malloc(sizeof(lines[0]) * num_lines);
// lines[0] = "First"; // This would assign a pointer to some static storage containing the bytes { 'F', 'i', 'r', 's', 't', '\0' }
lines[0] = strdup("First"); // Use strdup() instead to allocate a copy of the string on the heap
lines[1] = strdup("Second"); // This is so that we don't end up with a mixture of strings
lines[2] = strdup("Third"); // with different kinds of storage in the same array
// because only the heap strings can be free()'d
// and trying to free() static strings is an error
// but you won't be able to tell them apart,
// they will all just look like pointers
// and you won't know which ones are safe to free()
printf("There are %d lines in the array.\n", num_lines);
// Reading the files this way only works for lines shorter than 255 characters
/*
printf("\nReading file...\n");
FILE *fp = fopen(files[0], "r");
char buffer[BUFFER_SIZE_BYTES];
while (fgets(buffer, BUFFER_SIZE_BYTES, fp) != NULL) {
printf("%s\n", buffer);
// Resize the array we allocated on the heap
void *ptr = realloc(lines, (num_lines + 1) * sizeof(lines[0]));
// Note that this can fail if there isn't enough free memory available
// This is also a comparatively expensive operation
// so you wouldn't typically do a resize for every single line
// Normally you would allocate extra space, wait for it to run out, then reallocate
// Either growing by a fixed size, or even doubling the size, each time it gets full
// Check if the allocation was successful
if (ptr == NULL) {
fprintf(stderr, "Failed to allocate memory at %s:%d\n", __FILE__, __LINE__);
assert(false);
}
// Overwrite `lines` with the pointer to the new memory region only if realloc() was successful
lines = ptr;
// We cannot simply lines[num_lines] = buffer
// because we will end up with an array full of pointers
// that are all pointing to `buffer`
// and in the next iteration of the loop
// we will overwrite the contents of `buffer`
// so all appended strings will be the same: the last line of the file
// So we strdup() to allocate a copy on the heap
// we must remember to free() this later
lines[num_lines] = strdup(buffer);
// Keep track of the size of the array
num_lines++;
}
fclose(fp);
printf("Done.\n");
*/
// I would recommend reading the file this way instead
///*
printf("\nReading file...\n");
FILE *fp = fopen(files[0], "r");
char *new_line = NULL; // This string is allocated for us by getline() and could be any length, we must free() it though afterwards
size_t str_len = 0; // This will store the length of the string (including null-terminator)
ssize_t bytes_read; // This will store the bytes read from the file (excluding null-terminator), or -1 on error (i.e. end-of-file reached)
while ((bytes_read = getline(&new_line, &str_len, fp)) != -1) {
printf("%s\n", new_line);
// Resize the array we allocated on the heap
void *ptr = realloc(lines, (num_lines + 1) * sizeof(lines[0]));
// Note that this can fail if there isn't enough free memory available
// This is also a comparatively expensive operation
// so you wouldn't typically do a resize for every single line
// Normally you would allocate extra space, wait for it to run out, then reallocate
// Either growing by a fixed size, or even doubling the size, each time it gets full
// Check if the allocation was successful
if (ptr == NULL) {
fprintf(stderr, "Failed to allocate memory at %s:%d\n", __FILE__, __LINE__);
assert(false);
}
// Overwrite `lines` with the pointer to the new memory region only if realloc() was successful
lines = ptr;
// Allocate a copy on the heap
// so that the array elements don't all point to the same buffer
// we must remember to free() this later
lines[num_lines] = strdup(new_line);
// Keep track of the size of the array
num_lines++;
}
free(new_line); // Free the buffer that was allocated by getline()
fclose(fp); // Close the file since we're done with it
printf("Done.\n");
//*/
printf("\nThere are %d lines in the array:\n", num_lines);
for (int i = 0; i < num_lines; i++) {
printf("%d: \"%s\"\n", i, lines[i]);
}
// Here you can do what you need to with the data...
// free() each string
// We know they're all allocated on the heap
// because we made copies of the statically allocated strings
for (int i = 0; i < num_lines; i++) {
free(lines[i]);
}
// free() the array itself
free(lines);
printf("\nProgram end.\n");
// At this point we should have free()'d everything that we allocated
// If you run the program with Valgrind, you should get the magic words:
// "All heap blocks were freed -- no leaks are possible"
return 0;
}
If you want to add elements to an array, you have 3 options:
Determine the maximum number of elements at compile-time and create a correctly sized arrray
Determine the maximum number of elements at run-time and create a variable-length array (works only in C99 and later)
Dynamically allocate the array and expand it as needed
Option 1 doesn't work here because it is impossible to know at compile-time how many lines your file will have.
Option 2 would imply that you first find the number of lines, which means to iterate the file twice. It also means that when you return from the function that reads the file, the array is automatically deallocated.
Option 3 is the best. Here is an example:
char **aLineToMatch;
FILE *file2;
int bufferLength = 255;
char buffer[bufferLength];
int i = 0;
char *testFiles[] = { "L_2005149PL.01002201.xml.html",
"L_2007319PL.01000101.xml.html",
NULL};
char (*testStrings)[bufferLength] = NULL; //pointer to an array of strings
//you probably meant file2 here (or the normal file in the while condition)
file2 = fopen(testFiles[0], "r"); // loop will come later, thats not the problem
while(fgets(buffer, bufferLength, file2) != NULL) {
printf("%s\n", buffer);
testStrings = realloc(testStrings, (i + 1) * sizeof testStrings[0]);
strcpy(testStrings[i], buffer);
i++;
}
fclose(file);
}
I am trying to create a small c program that will read a string with arbitrary size, without having any memory leaks.
According to my research, the function malloc can be used to allocate a number of bytes for whatever data we want to store.
In my program, I start by allocating space for 0 characters, and I make the pointer word point to it. Then whenever I read a single character, I make a pointer oldWord that points to word, which frees the old memory location once I allocate a larger memory location for the new character.
My research shows that the function free can be used to free an old memory location that is no longer needed. However, I am not sure where I am going wrong. Below you can see my code.
#include <stdio.h>
#include <stdlib.h>
int main(void){
char *word = malloc(0);
printf("Enter name: ");
readWord(word);
printf("Your name is: %s\n", word);
free(word);
word = realloc(0);
printf("Enter name: ");
readWord(word);
printf("Your name is: %s\n", word);
free(word);
return 0;
}
void readWord(char *word){
int i = 0;
char *oldWord, c = getchar();
while(c != ' ' && c != '\n'){
oldWord = word;
word = realloc(word, i + 1);
free(oldWord);
word[i++] = c;
c = getchar();
}
oldWord = word;
word = realloc(word, i + 1);
free(oldWord);
word[i] = '\0';
}
The problem as I see it here is with
free(oldWord);
without checking the failure of realloc(). In case realloc() is success, passing the same pointer to free() causes undefined behavior.
That said, some more notes
a syntax like
word = realloc(word, i + 1);
is dangerous, in case realloc() fails, you'll lose the actual pointer, too. You should use a temporary pointer to hold the return value of realloc(), check for success and only then, assign it back to the original pointer, if you need.
In your code, c is of char type, which may not be sufficient to hold all the possible values returned by getchar(), for example, EOF. You should use an int type, that is what getchar() returns.
There are multiple problems in your code:
you free the pointer you passed to realloc(). This is incorrect as realloc() will have freed the memory already if the block was moved.
Otherwise the pointer is freed twice.
The pointer reallocated bu readWord() is never passed back to the caller.
Allocating a 0 sized block has unspecified behavior: it may return NULL or a valid pointer that should not be dereferenced but can be passed to free() or realloc().
You do not test for end of file: there is an infinite loop if the file does not have a space nor a linefeed in it, for example if the file is empty.
you do not have a prototype for readWord() before it is called.
Here is an improved yet simplistic version:
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
char *readWord(void);
int main(void) {
char *word;
printf("Enter name: ");
word = readWord();
if (word == NULL) {
printf("Unexpected end of file\n");
else
printf("Your name is: %s\n", word);
free(word);
return 0;
}
char *readWord(void) {
int c;
size_t i = 0;
char *word = NULL;
while ((c = getchar()) != EOF && !isspace(c)) {
word = realloc(word, i + 2);
if (word == NULL)
break;
word[i++] = c;
word[i] = '\0';
}
return word;
}
I'm writing a C program that should read in an essay from a user. The essay is divided into multiple paragraphs.
I don't know how many lines or characters the essay will be, but I do know that it ends with a hash symbol (#). I want to use only as much memory as is necessary to hold the essay.
Here is what I have tried so far:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
main(){
int size;
char *essay;
printf("\n how many characters?\n");
scanf("%d", &size);
essay =(char *) malloc(size+1);
printf("Type the string\n");
scanf("%s",essay);
printf("%s",essay );
}
As I said before, I don't know (and don't want to ask) about the number of characters beforehand. How do I dynamically allocate memory to save space? (What is dynamic memory allocation?) Is there another way to save memory that doesn't rely on dynamic allocation?
Additionally, my code only reads one line at a time right now. How can I read multiple lines and store them as a single string?
this is another code
#include <stdio.h>
#include <stdlib.h>
int main ()
{
char input;
int count = 0;
int n;
char* characters= NULL;
char* more_characters = NULL;
do {
printf ("type the essay:\n");
scanf ("%d", &input);
count++;
more_characters = (char*) realloc (characters, count * sizeof(char));
if (more_characters!=NULL) {
characters=more_characters;
characters[count-1]=input; }
else {
free (characters);
printf ("Error (re)allocating memory");
exit (1);
}
} while (input!='#');
printf ("the essay: ");
for (n=0;n<count;n++) printf ("%c",characters[n]);
free (characters);
}
it is not working
You can read character at a time and copy it into your essay buffer. When your essay buffer runs out of space, you can do a realloc to get another chunk of memory. When your character that you read is a "#" you're done.
Hmmm to "not waste space in memory",
then how about excessive calls of realloc()?
char *Read_Paragraph_i(void) {
size_t size = 0;
size_t i = 0;
char *dest = NULL;
int ch;
while ((ch = fgetc(stdin)) != EOF) {
if (ch == '#') break;
size++;
char *new_ptr = realloc(dest, size);
assert(new_ptr);
dest = new_ptr;
dest[i++] = ch;
}
size++;
char *new_ptr = realloc(dest, size+);
assert(new_ptr);
dest = new_ptr;
dest[i++] = '\0';
return dest;
}
A more sane approach would double the allocation size every time more memory is need, temporally wasting memory and then a final "right-size" allocation.
If this can use C++, you can use string (std::string) which will grow as needed as characters are added. If you can't then you will have to use malloc to create an array to hold characters. When it is full, you will have to create a new one, and copy the current data from old to new one, then add the new character. You can do that on each character read to use the minimal amount of memory, but that is WAY too inefficient. A better way is to allocate the character array in chucks, keeping the current size, and the number of characters currently in it. When you want to add another character and the array is full, then you allocate a new one that is some number of characters larger than current one, update current size to size of new one, then add new character.
I want to read values (float) into an array but I don't know number of values.
My input is this
Enter values: 1.24 4.25 1.87 3.45 .... etc
How can I load this input to an array? I know that input ends when enterring 0 or EOF.
while(0 or EOF){
scanf("%f", &variable[i])
i++;
}
Thank you.
You can dynamically allocate the array and then reallocate the memory for it when the previously allocated buffer is full. Note that the conversion specifier %f in the format string of scanf reads and discards the leading whitespace characters. From the man page of scanf -
scanf returns the number of items successfully matched and assigned
which can be fewer than provided for, or even zero in the event of an
early matching failure. The value EOF is returned if the end of input
is reached before either the first successful conversion or a matching
failure occurs.
This means that scanf will return EOF only when it encounters EOF as the first input when it is called because EOF must be preceded with a newline '\n' else it won't work (depending on the OS). Here's a small program to demonstrate how you can do it.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
size_t len = 4;
float *buf = malloc(len * sizeof *buf);
if(buf == NULL) { // check for NULL
printf("Not enough memory to allocate.\n");
return 1;
}
size_t i = 0;
float *temp; // to save buf in case realloc fails
// read until EOF or matching failure occurs
// signal the end of input(EOF) by pressing Ctrl+D on *nix
// and Ctrl+Z on Windows systems
while(scanf("%f", buf+i) == 1) {
i++;
if(i == len) { // buf is full
temp = buf;
len *= 2;
buf = realloc(buf, len * sizeof *buf); // reallocate buf
if(buf == NULL) {
printf("Not enough memory to reallocate.\n");
buf = temp;
break;
}
}
}
if(i == 0) {
printf("No input read\n");
return 1;
}
// process buf
for(size_t j = 0; j < i; j++) {
printf("%.2f ", buf[j]);
// do stuff with buff[j]
}
free(buf);
buf = NULL;
return 0;
}
I guess your actual concern is the unknown number of floats that user is going to input. You can use pointer to float, do malloc for some predefined size, if your limit has reached while taking an input then do a realloc to increase the memory. You need to take care of previously accepted data while doing a reaccloc.
You need a dynamic allocation of your array since you don't know its size at compile time.
// INITIAL_SIZE can be the average expected size of your array
#define INITIAL_SIZE 4
// size will track the current maximum size of youe array.
size_t size = INITIAL_SIZE;
// dynamic allocation for variable
float* variable = malloc(sizeof(float)*size);
// check that the allocation happened correctly
assert(variable != NULL);
// i contains the current actual size of your array
int i = 0;
while (0 or EOF) {
if (i >= size) {
// if the array is getting bigger than its max size, resize it.
size *= 2;
// This will reallocate enough memory for variable.
variable = realloc(variable, sizeof(float)*size);
// check that the allocation happened correctly;
assert(variable != NULL);
// (NB: It IS important to affect variable to the result of
// realloc, you can't simply realloc as in some cases the
// original pointer will become invalid!)
}
scanf("%f", &variable[i])
i++;
}
As an aside, please note that variable is not a wonderful variable name. Use a name describing what your variable is used for.
EDIT: corrected the size in realloc to alloc size*2 floats and avoid it break horribly, as unwind pointed out.
i = 0;
while(scanf("%f", &variable[i])!=-1)
{
i++;
}
scanf returns -1 when it tries to read after EOF.
These are the instructions:
"Read characters from standard input until EOF (the end-of-file mark) is read. Do not prompt the user to enter text - just read data as soon as the program starts."
So the user will be entering characters, but I dont know how many. I will later need to use them to build a table that displays the ASCII code of each value entered.
How should I go about this?
This is my idea
int main(void){
int inputlist[], i = -1;
do {++i;scanf("%f",&inputlist[i]);}
while(inputlist[i] != EOF)
You said character.So this might be used
char arr[10000];
ch=getchar();
while(ch!=EOF)
{
arr[i++]=ch;
ch=getchar();
}
//arr[i]=0; TO make it a string,if necessary.
And to convert to ASCII
for(j=0;j<i;j++)
printf("%d\n",arr[j]);
If you are particular in using integer array,Use
int arr[1000];
while(scanf("%d",&arr[i++])!=EOF);
PPS:This works only if your input is one character per line.
scanf returns EOF on EOF
You have a reasonable attempt at a start to the solution, with a few errors. You can't define an array without specifying a size, so int inputlist[] shouldn't even compile. Your scanf() specifier is %f for float, which is wrong twice (once because you declared inputlist with an integer type, and twice because you said your input is characters, so you should be telling scanf() to use %c or %s), and really if you're reading input unconditionally until EOF, you should use an unconditional input function, such as fgets() or fread(). (or read(), if you prefer).
You'll need two things: A place to store the current chunk of input, and a place to store the input that you've already read in. Since the input functions I mentioned above expect you to specify the input buffer, you can allocate that with a simple declaration.
char input[1024];
However, for the place to store all input, you'll want something dynamically allocated. The simplest solution is to simply malloc() a chunk of storage, keep track of how large it is, and realloc() it if and when necessary.
char *all_input;
int poolsize=16384;
all_input = malloc(pool_size);
Then, just loop on your input function until the return value indicates that you've hit EOF, and on each iteration of the loop, append the input data to the end of your storage area, increment a counter by the size of the input data, and check whether you're getting too close to the size of your input storage area. (And if you are, then use realloc() to grow your storage.)
You could read the input by getchar until reach EOF. And you don't know the size of input, you should use dynamic size buffer in heap.
char *buf = NULL;
long size = 1024;
long count = 0;
char r;
buf = (char *)malloc(size);
if (buf == NULL) {
fprintf(stderr, "malloc failed\n");
exit(1);
}
while( (r = getchar()) != EOF) {
buf[count++] = r;
// leave one space for '\0' to terminate the string
if (count == size - 1) {
buf = realloc(buf,size*2);
if (buf == NULL) {
fprintf(stderr, "realloc failed\n");
exit(1);
}
size = size * 2;
}
}
buf[count] = '\0';
printf("%s \n", buf);
return 0;
Here is full solution for your needs with comments.
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
// Number of elements
#define CHARNUM 3
int main(int argc, char **argv) {
// Allocate memory for storing input data
// We calculate requested amount of bytes by the formula:
// NumElement * SizeOfOneElement
size_t size = CHARNUM * sizeof(int);
// Call function to allocate memory
int *buffer = (int *) calloc(1, size);
// Check that calloc() returned valid pointer
// It can: 1. Return pointer in success or NULL in faulire
// 2. Return pointer or NULL if size is 0
// (implementation dependened).
// We can't use this pointer later.
if (!buffer || !size)
{
exit(EXIT_FAILURE);
}
int curr_char;
int count = 0;
while ((curr_char = getchar()) != EOF)
{
if (count >= size/sizeof(int))
{
// If we put more characters than now our buffer
// can hold, we allocate more memory
fprintf(stderr, "Reallocate memory buffer\n");
size_t tmp_size = size + (CHARNUM * sizeof(int));
int *tmp_buffer = (int *) realloc(buffer, tmp_size);
if (!tmp_buffer)
{
fprintf(stderr, "Can't allocate enough memory\n");
exit(EXIT_FAILURE);
}
size = tmp_size;
buffer = tmp_buffer;
}
buffer[count] = curr_char;
++count;
}
// Here you get buffer with the characters from
// the standard input
fprintf(stderr, "\nNow buffer contains characters:\n");
for (int k = 0; k < count; ++k)
{
fprintf(stderr, "%c", buffer[k]);
}
fprintf(stderr, "\n");
// Todo something with the data
// Free all resources before exist
free(buffer);
exit(EXIT_SUCCESS); }
Compile with -std=c99 option if you use gcc.
Also you can use getline() function which will read from standard input line by line. It will allocate enough memory to store line. Just call it until End-Of-File.
errno = 0;
int read = 0;
char *buffer = NULL;
size_t len = 0;
while ((read = getline(&buffer, &len, stdin)) != -1)
{ // Process line }
if (errno) { // Get error }
// Process later
Note that if you are using getline() you should anyway use dynamic allocated memory. But not for storing characters, rather to store pointers to the strings.