Getline to get stdin is being skipped - c

I'm trying to get input from the user in the console, but I'm having problems with the function getline() in my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <memory.h>
#include <sys/wait.h>
#include <errno.h>
int main(int argc, char *argv[])
{
//check that the number of arguments given is valid
if (argc != 2){
printf("Error: arguments. \nThe file should only take one argument which is the name of the level\n");
exit(1);
}
char test[5];
int nb_lettres=strlen(argv[1]);
strncpy(test,argv[1]+nb_lettres-4,4);
//check that the file given is either a .tgz or a .tar
test[4]='\0';
if(strcmp(test,".tar")!=0 && strcmp(test,".tgz")!=0)
{
printf("Error: arguments. \nThe argument should be a file having the extension .tar or .tgz \n");
exit(2);
}
int status; //START OF THE PART CONTAINING THE PROBLEM
pid_t pid;
//create the folder then move to it, then extract the tar
if((pid=fork())!=0){
if(fork()){
execlp("mkdir","mkdir","leaSHdir",NULL);
}
//waiting to make sure we don't try to go in the folder before it's fully created
wait(&status);
execlp("tar","tar", "-xf", argv[1], "-C", "leaSHdir/",NULL);
}
waitpid(pid,&status,0);
printf("Extracting the files..\n");
sleep(1); //END OF THE PART CONTAINING THE PROBLEM
//Read the meta file
FILE *file;
chdir("./leaSHdir");
file=fopen("meta","r");
if (file==NULL){
// printf("Oh dear, something went wrong with read()! %s\n", strerror(errno));
printf("Error: meta. \nImpossible to read the meta file. Please check that it does exist (without looking in, vile cheater)\n");
exit(3);
}
char *line=NULL;
size_t len=0;
//Saving the commands which will be used by the user
char *result=NULL;
char **commands = malloc(5 * sizeof *commands);
int i=0;
if(commands==NULL){
printf("Error: memory. \nA problem occured with the memory while creating a pointer\n");
exit(4);
}
while(getline(&line,&len,file)!=-1){
if(strstr(line,"$")!=NULL){
commands[i]=(malloc(strlen(line)));
strcpy(commands[i],line+2);
//if the array is full,we add space for the next incoming command
if(i >= 4){
commands=realloc(commands,sizeof *commands *(i+2));
}
i++;
}
if(line[0]=='>'){
result=malloc(strlen(line));
strcpy(result,line+2);
}
}
int a = 0;
for (a = 0;a<i;a++){
printf("%s",commands[a]);
}
printf("%s",result);
printf("Erasing meta..");
unlink("meta");
printf("meta erased.\n");
int c;
while((c = getchar()) != '\n' && c != EOF){
printf("rien\n");
}
ssize_t r = getline(&line,&len,stdin);
printf("%d '%s' %d",(int) r, line, c);
char machin[2555];
scanf("%s",machin);
printf("%s test",machin);
free(commands);
free(result);
return 0;
}
When I execute this code, the last getline is completely skipped (the first one is working without any problem), which I don't see why. I've also tried using different functions (fgets, scanf) and both were also skipped.
Thanks in advance for any help which can be provided :)
Edit:
Changed the faulty getline line with ssize_t r = getline(&line,&len,stdin); printf("%d '%s' %d",(int) r, line, c);, here's the result:
cat
ls
man
Bravo! C'est ici!//this line and the 3 other lines before are the lines read by the first getline which is working
Erasing meta..meta erased.
-1 '> Bravo! C'est ici!
' -1
So basically, I don't even have time to type anything, I get this result directly without entering anything. Also the content of line isn't changed after the second getline considering it still contains the result from the first getline.
Edit 2 :
Okay, I think I found from where comes the problem: Basically, it's from a part of the code i didn't put in the extract there because I though it was not related at all with my current problem, so I've edited the whole extract to put it fully. I've put two comments to mark the part containing the problem. Although I don't see what could be causing it, considering this part contains only forks.
Although, sorry for the trouble, guys, should have put the whole code at the start
Last edit:
Figured out what was the problem: if((pid=fork())!=0){ which means that once my forks ended I was working on the child process and not on the father as I thought. Once I've changed it to if((pid=fork())==0){ everything worked fine. Thanks for the help :)

[Edit]
After some edits:
OP's problem occurs when using stdin after fork().
Similar to Two processes reading the same stdin
Code is unable to take in additional input as stdin has all ready reached the EOF condition or a rare IO error. That is the -1 return values from getline() and getchar(). line simply retains its former contents as nothing was changed.
char c;
while((c = getchar()) != '\n' && c != EOF);
ssize_t r = getline(&line,&len,stdin); //getline not working
printf("%d '%s' %d",(int) r, line, c);
-1 '> Bravo! C'est ici!
' -1
Additional issue: realloc() too late.
strcpy(commands[5],line+2); writes to unallocated memory.
char **commands=malloc(sizeof(char**)*5);
int i=0;
...
// In loop, i becomes 5.
...
strcpy(commands[i],line+2);
if (i > 5){
commands=realloc(commands,sizeof(char**)*(i+2));

Put somtehing before getilne to consume the trailing '\n' character. For example:
while ( getchar() != '\n' );
getline(&line,&len,stdin);

Related

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 files with the same extension in a directory and count their lines

I am having this problem with my code. I've been trying to open files that have the same extension and read the number of lines in the file that is in the directory.
So, here is what I've done:
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
int countLines(char name[]);
int main()
{
struct dirent *de;
DIR *dr=opendir(".");
char check[16]=".nkt";
int i;
char name[64];
int count=0;
if(dr==NULL)
{
printf("Didn't open!");
return 0;
}
while((de=readdir(dr))!=NULL)
{
if((strstr(de->d_name, check))!=NULL)
{
strcpy(name, de->d_name);
countLines(name);
}
}
closedir(dr);
return 0;
}
int countLines(char name[])
{
FILE *fp;
fp=fopen(name,"r");
char ch;
int lines=0;
while(!feof(fp))
{
ch=fgetc(fp);
if(ch=='\n')
{
lines++;
}
}
fclose(fp);
printf("%d\n", lines);
}
and the result that I am getting is always like :
2
2
2
Even though every file has 54 lines.
Would gladly appreciate some help.
PS. The extension is .nkt
The countLines() function you show is stepping into several traps.
fgetc() returns int not char by intention. It does this to be able to return the End-of-File state, aside all other possible character values. A simple char cannot do this.
The use of feof() to identify the End-of-File fails as the EOF indicator is set only after the last read hitting the end of the file has been completed. So a loop steered using feof() typically iterated one time to often.
A detailed discussion on this is here.
A text file's last line not necessarily carries an End-of-File indicator, but you mostly likely still want count that line. Special logic needs to be applied to cover this case.
A possible implementation of a function taking care off all those issue mentioned above might look like this:
#include <stdio.h>
/* Returns the number of lines inside the file named file_name
or -1 on error. */
long count_lines(const char * file_name)
{
long lines = 0;
FILE * fp = fopen(file_name, "r"); /* Open file to read in text mode. */
if (NULL == fp)
{
lines = -1;
}
else
{
int previous = EOF;
for (int current; (EOF != (current = fgetc(fp)));)
{
if ('\n' == current)
{
++lines;
}
previous = current;
}
if (ferror(fp)) /* fgetc() returns EOF as well if an error occurred.
This call identifies that case. */
{
lines = -1;
}
else if (EOF != previous && '\n' != previous)
{
++lines; /* Last line missed trailing new-line! */
}
fclose(fp);
}
return lines;
}
Regarding the discussion about different End-of-Line indicators inside the question's comment section:
The End-of-Line indicator for text files is implemented differently on different platforms (UNIX: '\n' vs. Windows: \r\n vs. ... (https://en.wikipedia.org/wiki/Newline)).
To manoeuvre around this the C library function fopen() by default opens a file in so called "text-mode". If opened this way the C implementation takes care that each line's end is returned as a single '\n' character, the so called "new-line" character. Please note (as mentioned above under 3.) that for the last line there might be no End-of-Line indicator at all.

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).

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?

Difficulty using malloc and scanf

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;
}

Resources