Difficulty using malloc and scanf - c

I have difficulty using malloc and fscanf.
I just want to read a file and print out the result using
I got a segmentation fault error when I executed this code.
I am not sure what I have done wrong. I would be very grateful if someone points out a fix.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]){
char* buffer = (char*)malloc(*argv[1]); // Allocate memory
if(buffer=NULL) // if *argv[1] is not existed, exit the program
exit(1);
int n = 0;
FILE* fp=fopen("file.txt","r"); // Open the file
do {
buffer[n] =fscanf(fp,"%c",buffer); // read from file until it gets EOF
} while(buffer[n] != EOF);
fclose(fp); // Close the file
printf("%s",buffer); // Print the stored string
free(buffer); // Return the memory
return 0;
}

Got it. This:
if(buffer=NULL)
should be this:
if(buffer==NULL)
You're setting buffer to NULL. I'm sure you can see what happens next.
More generally, this code is trying to do several things, and it's full of bugs. You should have tested the different functions separately and worked out those bugs along the way.

This here seems wrong:
char* buffer = (char*)malloc(*argv[1]);
The command line argument is a string, but you want a number. You have to convert the string to a number first.
Another problem: In your loop n is never increased, which is why only the first byte of the buffer is written.

Please find the fixed code and the comments inline:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
// Add the check if *argv[1] does not exist, exit the program
long mem_sz=strtol(argv[1],NULL,10);//Safer to atoi
char* buffer = (char*)malloc(mem_sz); // properly allocate memory
//You missed the == in the NULL check.
if(buffer==NULL)
exit(1);
int n = 0;
FILE* fp=fopen("file.txt","r"); // Open the file
if (fp == NULL)//Check fp too
exit(1);
do
{
buffer[n++]=fscanf(fp,"%c",buffer);
} // read from file until it gets EOF and n++
while(buffer[n-1] != EOF);//Check the last read character
buffer[n]=0;//Put an end of string, so that printf later will work correct
fclose(fp); // Close the file
printf("%s\n",buffer); // Print the stored string
free(buffer); // Return the memory
return 0;
}

Related

C Using char* in fscanf causing error Segmentation fault: 11

I am new to C and I came across an issue when using fscanf to read all strings from a .txt file.
The code is as follow:
#include <stdlib.h>
#include <stdio.h>
int main() {
FILE *spIn;
char *numIn;
spIn = fopen("data.txt", "r");
if (spIn == NULL) {
printf("Can't Open This File \n");
}
while ((fscanf(spIn, "%s", numIn)) == 1) {
printf("%s\n", numIn);
};
fclose(spIn);
return 1;
}
This throws an error: Segmentation fault: 11.
The original data on txt file is:
1 2 345 rrtts46
dfddcd gh 21
789 kl
a mix of ints, strings, white space and newline characters.
At least 4 candidate undefined behaviors (UB) that could lead to a fault of some kind.
Code fails to pass to fscanf(spIn,"%s",numIn) an initialized pointer.
Code calls fscanf() even if fopen() fails.
Code calls fclose() even if fopen() fails.
No width limit in fscanf(spIn,"%s",numIn)), worse than gets().
Text files really do not have strings ('\0' terminated data) nor int, they have lines (various characters with a '\n' termination).
To read a line in and save as a string, use fgets(). Do not use fscanf() to read lines of data.
#include <stdlib.h>
#include <stdio.h>
int main() {
FILE *spIn = fopen("data.txt", "r");
if (spIn == NULL) {
printf("Can't Open This File \n");
} else {
char buf[100];
while (fgets(buf, sizeof buf, spIn)) {
printf("%s", buf);
}
fclose(spIn);
}
}
char* numIn is a pointer, and it is uninitalized, you can't really store anything in it, you need to either allocate memory for it or make it point to some valid memory location:
#include<stdlib.h> // for malloc
char* numIn = malloc(100); // space for 99 char + null terminator byte
//...
while ((fscanf(spIn, "%99s", numIn)) == 1)
{
printf("%s\n",numIn);
};
Or:
char str[100];
char *numIn = str;
Which in this small code makes little sense, you should probably make numIn a fixed size array to begin with:
char numIn[100];
Note that that you should use a width specifier in *scanf to avoid buffer overflow. This still has a problem though, it will read word by word, instead of line by line.
Looking at your input file, using fgets seems like a better option, it can read complete lines, including spaces:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
FILE *spIn;
char numIn[100];
spIn = fopen("data.txt", "r");
if (spIn != NULL)
{
while ((fgets(numIn, sizeof numIn, spIn)))
{
numIn[strcspn(numIn, "\n")] = '\0'; // removing \n
printf("%s\n", numIn);
}
fclose(spIn);
}
else
{
perror("Can't Open This File");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Since fgets also parses the \n character, I'm removing it with strcspn.
Though you do verify the return value of fopen the execution continues even if it fails to open, I also addressed that issue.

Why does the program print only the last line of the file, even after reading the entire file?

I want to write a program in C which just reads a file, stores it into an array and then prints the array. Everything works fine but when the text file has more than one line, I always just get the last line printed out.
This is my Code:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char * argv[]) {
FILE * stream;
char dateiname[255];
stream = fopen("heute.txt", "r");
if(stream == NULL){
printf("Error");
}else {
while(!feof(stream)){
fgets(dateiname, 255, stream);
}
fclose(stream);
}
printf("%s\n", dateiname);
}
Thanks for help!
Everything works fine but when the text file has more than one line, I always just get the last line printed out
Reason: For every iteration, the data gets replaced with the next line data, and at the end dateiname will read only the last line.
while(!feof(stream))
Usage of feof() is not recommended. Please see this link for more information :https://faq.cprogramming.com/cgi-bin/smartfaq.cgi?id=1043284351&answer=1046476070
Please see the following code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *stream;
char dateiname[1024];
int i = 0;
stream = fopen("heute.txt", "r");
if (stream == NULL)
{
printf("Error");
}
else
{
while (fgets(dateiname, sizeof(dateiname), stream) != NULL)
{
printf("Line %4d: %s", i, dateiname);
i++;
}
}
return 0;
}
If you want to just read and print the contents of the file you no need to worry about the size of the file and how many number of lines you have in file.
you can just run fgets() in the while and print each line until we reach NULL
But if you want to store them, we need to calculate the size of the file.
So we need to use functions like stat or fstat to get the size of the file and allocate memory dynamically then just read that many bytes.

Reading information from a file in C language

So I have the txt file from which I need to read the number of students written in that file, and because every student is in separate line, it means that I need to read the number of lines in that document. So I need to:
Print all lines from that document
Write the number of lines from that document.
So, I write this:
#include "stdafx.h"
#include <stdio.h>
int _tmain(int argc, _TCHAR* Argo[]){
FILE *student;
char brst[255];
student = fopen("student.txt", "r");
while(what kind of condition to put here?)
{
fgetc(brst, 255, (FILE*)student);
printf("%s\n", brst);
}
return 0;
}
Ok, I understand that I can use the same loop for printing and calculating the number of lines, but I can't find any working rule to end the loop. Every rule I tried caused an endless loop. I tried brst != EOF, brst != \0. So, it works fine and print all elements of the document fine, and then it start printing the last line of document without end. So any suggestions? I need to do this homework in C language, and I am using VS 2012 C++ compiler.
OP's code is close but needs to use fgets() rather than fgetc() and use the return value of fgets() to detect when to quit, it will be NULL #Weather Vane. Also add a line counter.
#include <stdio.h>
int main(void) {
FILE *student = fopen("student.txt", "r");
unsigned line_count = 0;
if (student) {
char brst[255];
// fgetc(brst, 255, (FILE*)student);
while (fgets(brst, sizeof brst, student)) {
line_count++;
printf("%u %s", line_count, brst);
}
fclose(student);
}
printf("Line Count %u\n", line_count);
return 0;
}
Try this:
#include "stdafx.h"
#include <stdio.h>
int _tmain(int argc, _TCHAR* Argo[]){
FILE *student;
char brst[255];
char* result = NULL;
//Ensure file open works, if it doesn't quit
if ((student = fopen("student.txt", "r")) == NULL)
{
printf("Failed to load file\n");
return 1;
}
//Read in the file
for ( (result = fgets( brst, sizeof(brst), student));
!feof(student);
(result = fgets( brst, sizeof(brst), student)) )
{
if ( result == NULL ) break; //I've worked on embedded systems where this actually ment waiting on data, not EOF, so a 'continue' would go here instead of break in that case
printf("%s\n", brst);
}
fclose( student );
return 0;
}
feof() is only true after you've read past the end of the file. Using a for with two identical reads, and feof() on the conditional is a simple way to ensure you read the file as expected.
Use feof() to check for an eof condition.
You are correctly reading the file line-by-line, but use fgets(), not fgetc() - and the cast is not needed.
Then use sscanf() to assign the line data to variables (or some "safe" form of it).

Read input into array results in segmentation violation

My program has the following requirements: If a command line argument is given, interpret it as a file name and read the input from that file. Otherwise, read input from stdin instead. As I am going to need the input later, I want to save it into an array. And because any non-ASCII characters are to be ignored, I decided to process the input character by character. This is my code:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define MAX_WORDS 999
#define MAX_WORD_LENGTH 50
typedef struct Data{
char words[MAX_WORDS][MAX_WORD_LENGTH+1];
int numwords;
} Data;
Data* data;
int main(int argc, char** argv){
data= malloc(sizeof data);
FILE* infile;
if(argc<=1){//if no arguments, read words from stdin
infile= stdin;
}else if(argc==2){//read words from file
infile= fopen(argv[1], "r");
if(infile==NULL){
printf("failed to open word file");
return 1;
}
}
char c;
int wordindex= 0;
int charindex= 0;
while(1){//read input character by character, only accepting ASCII characters
c= fgetc(infile);
if(c=='\n' || c==EOF){
data->words[wordindex][charindex]= '\0';
wordindex++;
charindex= 0;
if(wordindex>=MAX_WORDS || c==EOF)
break;
continue;
}
if(!isascii(c))
continue;
data->words[wordindex][charindex]= toupper(c);
charindex++;
if(charindex>=MAX_WORD_LENGTH){
wordindex++;
charindex= 0;
if(wordindex>=MAX_WORDS)
break;
}
}
if(argc==2) fclose(infile);
data->numwords= wordindex-1;
//check if everything worked as intended
printf("==================\n%d word(s) read:\n", data->numwords);
for (int i = 0; i < data->numwords; i++)
printf("%d %s\n", (int)strlen(data->words[i]), data->words[i]);
}
Everything works fine if I enter the input through stdin, but if I attempt to read the input from a text file, the program segfaults. It seems to work if the text file contains only one line of text, but if there are two or more then it crashes. I'm a beginner in C and I don't see any difference between reading from stdin or a file, so I have no idea why this is happening. Can somebody enlighten me?
This
Data* data;
data= malloc(sizeof data);
allocates bytes to suite the size of data, with data being "just" a pointer to Data, not Data itself. A pointer is 4/8 bytes depending whether on a 32/64 bit platform.
Allocating to few memory here leads to writing to invalid memory soon and with this invoking the infamous Undefined Behaviour. From this moment on anything can happen ranging from crash to nothing.
If you want the number of bytes to hold Data you want to allocate like this
data = malloc(sizeof (Data));
of even better like this
data = malloc(sizeof *data);
Also one should test the outcome of relevant system call, also malloc() could fail:
if (NULL == data)
{
perror("malloc() failed");
exit(EXIT_FAILURE);
}

Data entry into array of character pointers in C

this is my first question asked on here so if I'm not following the formatting rules here please forgive me. I am writing a program in C which requires me to read a few lines from a file. I am attempting to put each line into a cstring. I have declared a 2D character array called buf which is to hold each of the 5 lines from the file. The relevant code is shown below
#include <stdlib.h>
#include <sys/types.h>
#include <sys/file.h>
#include <sys/socket.h>
#include <sys/un.h> /* UNIX domain header */
void FillBuffersForSender();
char buf[5][2000]; //Buffer for 5 frames of output
int main()
{
FillBuffersForSender();
return 0;
}
void FillBuffersForSender(){
FILE *fp;
int line = 0;
char* temp = NULL;
size_t len = 0;
ssize_t read;
fp = fopen("frames.txt", "r");
printf("At the beginning of Fill Buffers loop.\n");
//while ((read = getline(&temp, &len, fp)) != -1){
while(line < 5){
//fprintf(stderr, "Read in: %s\n", temp);
fgets(temp, 2000, fp);
strcpy(buf[line], temp);
line++;
fprintf(stderr, "Line contains: %s.\n", temp);
temp = NULL;
}
while(line != 0){
fprintf(stderr, "Line contains: %s.\n", buf[line]);
line--;
}
}
The line
strcpy(buf[line], temp);
is causing a segmentation fault. I have tried this numerous ways, and cannot seem to get it to work. I am not used to C, but have been tasked with writing a bidirectional sliding window protocol in it. I keep having problems with super basic issues like this! If this were in C++, I'd be done already. Any help anyone could provide would be incredible. Thank you.
temp needs to point to an allocated buffer that fgets can write into.
In C programming, error checking is an important part of every program (in fact sometimes it seems like there's more error handling code than functional code). The code should check the return value from every function to make sure that it worked, e.g. if fopen returns NULL then it wasn't able to open the file, likewise if fgets returns NULL it wasn't able to read a line.
Also, the code needs to clean up after itself. For example, there is no destructor that closes a file when the file pointer goes out of scope, so the code needs to call fclose explicitly to close the file when it's finished with the file.
Finally, note that many of the C library functions have quirks that need to be understood, and properly handled. You can learn about these quirks by reading the man pages for the functions. For example, the fgets function will leave the newline character \n at the end of each line that it reads. But the last line of a file may not have a newline character. So when using fgets, it's good practice to strip the newline.
With all that in mind, the code should look like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXLINE 5
#define MAXLENGTH 2000
static char buffer[MAXLINE][MAXLENGTH];
void FillBufferForSender(void)
{
char *filename = "frames.txt";
FILE *fp;
if ((fp = fopen(filename, "r")) == NULL)
{
printf("file '%s' does not exist\n", filename);
exit(1);
}
for (int i = 0; i < MAXLINE; i++)
{
// read a line
if (fgets( buffer[i], MAXLENGTH, fp ) == NULL)
{
printf("file does not have %d lines\n", MAXLINE);
exit(1);
}
// strip the newline, if any
size_t newline = strcspn(buffer[i], "\n");
buffer[i][newline] = '\0';
}
fclose(fp);
}
int main(void)
{
FillBufferForSender();
for (int i = 0; i < MAXLINE; i++)
printf("%s\n", buffer[i]);
}
Note: for an explanation of how strcspn is used to strip the newline, see this answer.
When it comes to C you have to think of the memory. Where is the memory for a point with NULL assigned to it? How can we copy something to somewhere that we have no space for?

Resources