The text file is a list of words similar to this. each world is on a new line
When i run my code, the only thing being printed is "hi".... how do i get it to continue to read the next lines
hi
hello
welcome
#include <stdio.h>
#include <stdlib.h>
int main()
{
char data[100];
// OPENS THE FILE
FILE *fp = fopen("/classes/cs3304/cs330432/Programs/StringerTest/people.txt", "r");
if (fp == NULL)
{
printf("Unable to open the file\n");
} else {
fscanf(fp, "%s", data);
printf("%s", data);
fclose(fp);
}
}
How to get fscanf to scan the next Line in C
Read the documentation of fscanf. You cannot scan lines with it. And fscanf can fail, and you should handle its failure.
A possible approach is to read the next line using fgets (or getline, or readline) and later to parse it using sscanf.
Be also aware that in 2021, UTF-8 is used everywhere. So document on paper what your program should do if your people.txt file contains a line like Être ou ne pas être or a line with СТАРЫНКЕВИЧ (in Cyrillic letters).
If allowed, use a recent GCC compiler as gcc -Wall -Wextra -g (asking for all warnings and debug info), improve your code to get no warnings, and then use the GDB debugger to understand the behavior of your program. You could install Debian on your laptop to get gcc and gdb
The documentation of your program could use EBNF notation to specify what are the valid inputs.
Consider generating parts of your C code with tools like GNU bison.
When fopen fails you could use perror to report the error.
You may want to read the wikipage about recursive descent parsing.
You may want to study -for inspiration- the source code of GNU coreutils.
Related
F
I'm using Graphviz to render .dot file as graphs, and typically I would write in my terminal :
dot -Tpng yourFile.dot -o yourOutput.png to produce a .png image representing my graph. (I'm using a Unix environment btw)
Now let's say I have the following C function:
#include <stdlib.h>
#include <string.h>
#define MAXSIZE 255
typedef struct placeholder mystruct;
struct placeholder {
...
}
void outputGraph(mystruct str, char* outputName) {
char command[MAXSIZE];
char* tmpFile = "temp.dot";
char imageFile[MAXSIZE];
snprintf(imageFile, MAXSIZE, "%s.png", outputName);
FILE* file = fopen(tmpFile, "w");
writeStructToFile(str, file);
snprintf(command, MAXSIZE, "dot -Tpng %s -o %s", tmpFile, imageFile);
system(command);
snprintf(command, MAXSIZE, "rm %s", tmpFile);
system(command);
}
(my function WriteStructToFile is another one that I made and is working properly so the problem is somewhere else)
From what I understood about the system() function, it should produce the image output just the same as when I execute the same command myself.
Well, it does execute without any errors, but there is no image in the directory where I'm working.
At first, I thought, it's easy, system() doesn't start a new shell in the same working directory, so I tried to see the output of system(pwd); and it was my current working directory. So back to the starting point.
I also tried to check the value system(command) by doing int status = system(command); and then printf("status : %d\n", status); and, well, it printed 0.
Now I'm kinda clueless, I really don't see why it doesn't produce the image output.
I'd be very interested in any ideas or even solutions you have.
This is not the most elegant code, but it works & may help you debug your problem. It calls dot in three different ways. All three work as expected.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main () {
char command[50];
int rc;
strcpy(command, "dot -Tdot this.gv" );
rc=system(command);
printf("\n\n+++ call #1 returned %d\n", rc);
strcpy(command, "dot -Tdot this.gv -oout1.dot" );
rc=system(command);
printf("\n\n+++ call #2 returned %d\n", rc);
strcpy(command, "dot -Tdot this.gv -o out2.dot" );
rc=system(command);
printf("\n\n+++ call #3 returned %d\n", rc);
return(0);
}
snprintf(command, MAXSIZE, "touch %s", tmpFile);
system(command);
Why do you code that?
You certainly don't need to use system(3) then touch(1). You could use appropriate syscalls(2) (open(2) and close(2) here) or at least fopen(3) followed by fclose(3).
You might in some cases consider using popen(3) with pclose(3)
Of course, after
snprintf(command, MAXSIZE, "dot -Tpng %s -o %s", tmpFile, imageFile);
int bad = system(command);
You need to first check that bad is 0 and you probably want to use stat(2) or access(2) to check that imageFile exists.
There could be many reasons why system with a dot command fails. For example, a bad $PATH variable. I suggest using popen(3) with pclose(3) and probably /usr/bin/dot in the command.
Compile your C code using GCC as gcc -Wall -Wextra -g and use GDB to debug your executable. Both strace(1) and ltrace(1) could help you understand the behavior of your program.
Consider reading Advanced Linux Programming and studying for inspiration the source code of some simple open source Linux shells, such as sash or (more complex) GNU bash.
Be aware that Graphviz could be used as a library.
I wasn't closing the temp.dot file in which I was writing. My mistake.
I shall now remember to always close files that I open!
A big thank you to everyone who helped on here.
(Whether it was for the problem or on how to use properly SO)
Following program with putw is not writing the required data in the file.
#include <stdio.h>
int main(void)
{
FILE *fp;
fp = fopen("a.txt", "w");
putw(25,fp);
putw(325,fp);
putw(425,fp);
fclose(fp);
return 0;
}
Program is compiled and executed like the following
gcc filename.c
./a.out
It is writing something in the file. Also if we read the integer using getw(), it is reading the value which is not available in the file. Even it is not the ASCII value.
When it is compiled with gcc filename.c -std=c99, it is showing implicit declaration warning error.
Is it required to link any library files to use putw/getw in c.
There is no function called putw in standard C, which is why you get compiler warnings. You probably meant to use putwc in wchar.h.
putw is an ancient function that exists on some platforms. Use fwrite and fread instead. You should also check the return value from putw. It may be telling you why it is failing.
So here is my code:
#include <stdio.h>
typedef struct dat{
int broj;
int sir;
}sir;
int main() {
sir sir;
FILE* fordat;
int i=0;
fordat = fopen("dattk.txt","w+");
while(i<100) {
i++;
sir.broj = i;
sir.sir=-i;
fprintf(fordat,"%d %d", sir.broj, sir.sir);
}
// fseek(fordat,0,SEEK_SET);
//rewind(fordat);
// fscanf(fordat,"%d %d",sir.broj,sir.sir);
printf("%d% %d",sir.broj,c);
fclose(fordat);
return 0;
}
I am studying in C and made this simple example program of writing and reading from a file...
If I remove the comments from either fseek or rewind or fscanf, the program runs.
However, if I remove the comments from fseek AND fscanf the program compiles, but crashes on run.
Can't figure out why...
Your fscanf call is broken - change:
fscanf(fordat,"%d %d",sir.broj,sir.sir);
to:
fscanf(fordat,"%d %d",&sir.broj,&sir.sir);
Important: if you had compiled with warnings enabled (e.g. gcc -Wall ...) then the compiler would have helpfully pointed out this mistake to you, thereby saving you time and effort. Always enable compiler warnings and take heed of them.
And one more thing: you have absolutely no error checking in your code - you should check for failure after fopen and all other calls which might potentially fail.
Well, I am learning programming in C, and I got an assignment to get 3 characters from an input text file into 3 variables and then print their ASCII values.
I wrote this code:
#include <stdio.h>
int main()
{
char a,b,c;
printf("Insert 3 characters:\n");
a=getch();
b=getch();
c=getch();
printf("%d, %d, %d",(int)a,(int)b,(int)c);
}
I opened a text file (input.txt) and wrote there: "abc".
I managed to compile the code with the MinGW compiler, and on the CMD window that I opened in the folder of the .exe file, I wrote: "Task.exe <input.txt".
The program ran normally. I mean, it waited for me to input 3 characters.
What have I done wrong in my work?
help me please :)
You are asked to read from an input text file.
Why don't you use fopen to open a file handle, and fgetc to read from it?
You could perhaps use fscanf. Don't forget to use the resulting count.
And of course, you should call fclose. Using perror is useful to handle error cases.
So start your code with something that checks that your program has an argument, then fopen it:
int main(int argc, char**argv) {
if (argc<2) { fprintf(stderr, "missing program argument\n");
exit(EXIT_FAILURE); };
FILE* fil = fopen(argv[1], "r");
if (!fil) { perror(argv[1]); exit(EXIT_FAILURE); };
Then run Task.exe input.txt in your console (no redirection needed!).
You should take the habit of reading the documentation of every function you are using, of testing failure cases, of compiling with all warnings & debug info (gcc -Wall -Wextra -std=c99 -g), and of using the debugger (gdb).
Is it possible to get the entire string on line reported through LINE macro.
Sample code:
#include <stdio.h>
#define LOG(lvl) pLog(lvl, __LINE__, __FILE__)
pLog(const char *str, int line, const char *file)
{
printf("Line [%u]: File [%s]", line, file);
}
int main ()
{
LOG("Hello"
"world");
return 0;
}
The output is: Line [13]: File [macro.c]
Now in a large code base i want to search this file and print the string "Hello world" present at line reported (in this case it is 13)
One way i was thinking is to search for this file first generate the output file with gcc -E do grep for pLog and save their string then grep for LOG in actual code file and save line number match the line number with the line number present in result and then do matching of index and print the string.
As string can be distributed across multiple lines (as in code Hello is in one line and world is in another line) so also need to take care of that.
Is there anyother best and fast way of doing it or gcc provide some option to convert back line and file to actual code
This is very easy to do with Clang. The following command dumps Abstract Syntax Tree (AST) for the file test.c to the file out:
clang -cc1 -ast-dump test.c > out
Looking at the AST in the generated file you can easily find the information you need:
(StringLiteral 0x1376cd8 <line:12:9, line:13:13> 'char [11]' lvalue "Helloworld")))
Clang gives start of the first token of the string (line:12:9), start of the last token of the string (line:13:13) and the full string ("Helloworld").
You can either parse the AST dump or use Clang API to get the same information. If this is not a one time task, I'd go for API since the AST dump format is more likely to change in the future.
All this of course make sense only if you have a reason not to print the string in pLog itself.