I apologize in advance for any orthographic or grammatical error due to the fact that English is not my mother tongue.
I'm new to HTML and I've made a C program to automate a repetitive encoding (creating button spoilers, asking for the hidden content and what's written on the button each time)
The thing is that I've been forced to convert all the text (array of char) I wanted to write in hexadecimal because it contained some of the reserved characters of C language...
The program runs smoothly and fits my needs for the moment but I'd like to know if there is another way than converting everything into hex.
Also, gcc gives me this warning twice :
format ‘%s’ expects argument of type ‘char ’, but argument 2 has type ‘char ()[50]’ [-Wformat]
after these kinds of lines :
scanf("%s", &hidden_text);
(hidden_text is an array of char initialized like :
char hidden_text[50];)
how do I fix that warning ? passing a %50s to scanf didn't work (the program ran but this warning bothers me and I'd be glad if anyone tell me a way out of it)
If anyone see a way of upgrading that program or have any hint, please help out the new programmer I am.
(just for the record, I'm using linux, Emacs is my IDE and I'm using gcc to compile)
Here is the source code (hope I don't get reported for posting too much text):
#include<stdlib.h>
#include<stdio.h>
#include<string.h> /*strlen use this*/
int number_of_spoilers=10; /* the number of spoiler buttons you want to create (changed that value so you can test fast)*/
int a=0;
int spoiler=0; /*the spoiler Id I need to pass between each part*/
char part0[14]="\x3c\x68\x74\x6d\x6c\x3e\x0d\x0a\x3c\x62\x6f\x64\x79\x3e";
char part1[9]="\x3c\x64\x69\x76\x20\x69\x64\x3d\x22";
char part2[23]="\x22\x20\x73\x74\x79\x6c\x65\x3d\x22\x64\x69\x73\x70\x6c\x61\x79\x3a\x6e\x6f\x6e\x65\x22\x3e";
char hidden_text[50];
char part3[100]="\x3c\x2f\x64\x69\x76\x3e\x3c\x62\x75\x74\x74\x6f\x6e\x20\x74\x69\x74\x6c\x65\x3d\x22\x43\x6c\x69\x63\x6b\x20\x74\x6f\x20\x73\x68\x6f\x77\x2f\x68\x69\x64\x65\x20\x63\x6f\x6e\x74\x65\x6e\x74\x22\x20\x74\x79\x70\x65\x3d\x22\x62\x75\x74\x74\x6f\x6e\x22\x20\x6f\x6e\x63\x6c\x69\x63\x6b\x3d\x22\x69\x66\x28\x64\x6f\x63\x75\x6d\x65\x6e\x74\x2e\x67\x65\x74\x45\x6c\x65\x6d\x65\x6e\x74\x42\x79\x49\x64\x28\x27";
char part4[53]="\x27\x29\x20\x2e\x73\x74\x79\x6c\x65\x2e\x64\x69\x73\x70\x6c\x61\x79\x3d\x3d\x27\x6e\x6f\x6e\x65\x27\x29\x20\x7b\x64\x6f\x63\x75\x6d\x65\x6e\x74\x2e\x67\x65\x74\x45\x6c\x65\x6d\x65\x6e\x74\x42\x79\x49\x64\x28\x27";
char part5[51]="\x27\x29\x20\x2e\x73\x74\x79\x6c\x65\x2e\x64\x69\x73\x70\x6c\x61\x79\x3d\x27\x27\x7d\x65\x6c\x73\x65\x7b\x64\x6f\x63\x75\x6d\x65\x6e\x74\x2e\x67\x65\x74\x45\x6c\x65\x6d\x65\x6e\x74\x42\x79\x49\x64\x28\x27";
char part6[27]="\x27\x29\x20\x2e\x73\x74\x79\x6c\x65\x2e\x64\x69\x73\x70\x6c\x61\x79\x3d\x27\x6e\x6f\x6e\x65\x27\x7d\x22\x3e";
char button_text[50];
char part7[9]="\x3c\x2f\x62\x75\x74\x74\x6f\x6e\x3e";
char part_end[16]="\x3c\x2f\x68\x74\x6d\x6c\x3e\x0d\x0a\x3c\x2f\x62\x6f\x64\x79\x3e";
FILE *f=NULL;
main(FILE *f)
{
f=fopen("/home/Spoilers.html","a");
if(f==NULL)
printf("Can't open file");
else{
fwrite(part0, sizeof(char), 14,f);
while(a!=number_of_spoilers){
printf("%s","button text ? :");
scanf("%s", &button_text);
printf("%s", "hidden text ? :");
scanf("%s", &hidden_text);
fwrite(part1, sizeof(char), 9,f);
char hex[5];
sprintf(hex, "%x", spoiler); /*change the spoilerId value to hexa*/
fwrite(&hex, sizeof(char), strlen(hex),f);
fwrite(part2, sizeof(char), 23,f);
fwrite(hidden_text, sizeof(char), strlen(hidden_text),f);
fwrite(part3, sizeof(char), 100,f);
fwrite(&hex, sizeof(char), strlen(hex),f);
fwrite(part4, sizeof(char), 53,f);
fwrite(&hex, sizeof(char), strlen(hex),f);
fwrite(part5, sizeof(char), 51,f);
fwrite(&hex, sizeof(char), strlen(hex),f);
fwrite(part6, sizeof(char), 27,f);
fwrite(button_text, sizeof(char), strlen(button_text),f);
fwrite(part7, sizeof(char), 9, f);
a=a+1; spoiler=spoiler+1;
}
fwrite(part_end, sizeof(char), 16,f); /*contain "</body></html>"*/
fclose(f);
}
}
Thanks by advance and have a good day (or night) !!
If you use scanf( "%s", ... ), the expcected argument is a char * because it just needs the address to copy the input into. If you declare char hidden_text[50]; then hidden_text already is the (constant) pointer to that array. So you have to call
scanf( "%s", hidden_text );
not
scanf( "%s", &hidden_text );
Even better is calling
scanf( "%49s", hidden_text );
to prevent your progam from crashing if the input is too long (note that the length within the format string doesn't include the terminating '\0').
Please try
scanf("%s", &hidden_text[0]);
because you have to pass the address of the first character of the string.
Others have already pointed out the cause of the warning with scanf. Your program has other issues, most of them stylistic.
You are not using a legal form of ´main´ - This should also give a warning in gcc:
main(FILE *f) ...
The function main is special in that it can only have certain signatures. Passing in a file handle is not one of them. (You're also masking your global variable FILE *f, which doesn't hurt in your case, but that's probably not what you wanted.) In your case, where you don't use any command-line arguments, you should use:
int main() ...
Your output is text, so you should use the output functions suited for null-terminated strings, fprintf, putc or fputs. The function fwrite writes raw data lof a certain length and can be used, but you'll always have to pass the correct string length. Speaking of which: Passing constant string lengths to hex-encoded strings like this:
fwrite(part2, sizeof(char), 23,f);
is recipe for disaster: What if your string changes? You'll have to update the call, too. You should at least use strlen(part2) instead of the constant 23.
You read your input with scanf. This is okay, but maybe not the best way: The strings scanned with scanf cannot contain spaces, they are, in effect, single words. You can use the %[...] syntax to specify which characers to read, but that's complicated in my opinion. I propose using fgets, which reads a whole line. (The resulting string does have a trailing newline, which you should remove before processing.)
The number of buttons is fixed in your program. That's okay for a simple program, but ultimately you want the number of buttons to be flexible. It would therefore be better to read until the end of input (Ctrl-D on Unix, Ctrl-Z on Windows). The input functions return special values to indicate the the end of input has been reached: scanf returns EOF and fgets returns NULL in that case.
The strings you write out as spoiler and button text should be "sanitised", i.e. characters that are special to HTML should be masked, such that the input <copy & paste> reads <copy & paste> in the output file.
And a final note: You write out the (longish) code to show and hide buttons for every button. You could shorten that by writing a function for this once and then calling that function.
Putting all that together, your program might now look like this:
#include<stdlib.h>
#include<stdio.h>
#include<string.h>
void print_html(FILE *f, const char *str)
{
while (*str) {
switch (*str) {
case '<': fprintf(f, "<"); break;
case '>': fprintf(f, ">"); break;
case '&': fprintf(f, "&"); break;
default: putc(*str, f);
}
str++;
}
}
int main()
{
FILE *f = fopen("Spoilers.html", "w");
int elid = 0;
if (f == NULL) {
fprintf(stderr, "Can't open file\n");
exit(0);
}
fprintf(f, "<html>\n<head>\n");
fprintf(f, "<script type=\"text/javascript\">\n");
fprintf(f, " function show_hide(elid) {\n");
fprintf(f, " var el = document.getElementById(elid);\n");
fprintf(f, " if (el) {\n");
fprintf(f, " if (el.style.display == 'none') {\n");
fprintf(f, " el.style.display = '';\n");
fprintf(f, " } else {\n");
fprintf(f, " el.style.display = 'none';\n");
fprintf(f, " }\n");
fprintf(f, " }\n");
fprintf(f, " }\n");
fprintf(f, "</script>\n");
fprintf(f, "</head>\n<body>\n");
for (;;) {
char button[50];
char hidden[50];
if (fgets(button, 50, stdin) == NULL) break;
button[strlen(button) - 1] = '\0';
if (fgets(hidden, 50, stdin) == NULL) break;
hidden[strlen(hidden) - 1] = '\0';
fprintf(f, "<div id=\"%04x\" style=\"display:none\">", elid);
print_html(f, hidden);
fprintf(f, "</div><button title=\"Click to show/hide content\" "
"type=\"button\" onclick=\"show_hide('%04x')\">", elid);
print_html(f, button);
fprintf(f, "</button>\n");
elid++;
}
fprintf(f, "</body>\n</html>\n");
fclose(f);
return 0;
}
Related
I am making a linked list of World Cup teams, when loading the teams I need to do a preload reading data from a csv file but reading 2-word countries makes it wrong
For example
Suppose that this is the csv file:
Arabia Saudita, Herve, Renard, Salman, C, 0, 1
First I read the country name, dt name, captain name, group and two numeric values that are part of the program, but the output is something like this:
Country:Arabia DT:Saudita Herve Renard Salman C 0 1 Captain: empty Group:Empty
The expected output would be
Country: Arabia Saudita DtName:Herve DtSurname:Renard CaptainName:Salman Group: C
I tried to do it with a txt file but it is the same since it reads the spaces and the program fails or prints wrong
This is a part of the code that fails
FILE *chargue = fopen("Precharge.csv", "r");
while (!feof(charge)) {
fscanf(charge, "%s\n", countryAux);
chargecountry(&team, countryAux);
fscanf(charge, "%s\n", nameDTAux);
fscanf(charge, "%s\n", surnameDTAux);
chargenameDT(&team, surnameDTAux, nameDTAux);
chargeCapitan(&team, nameCapaux);
fscanf(charge, "%c\n", &groupAux);
chargegropu(&team, groupAux);
fscanf(charge, "%d\n", &actualscoreaux);
chargeactualscore(&team, actualscoreaux);
fscanf(charge, "%d\n", &faseActualaux);
chargeFase(&team, faseActualaux);
insert(lis, team);
forwards(lis);
}
Your format strings parse single words and do not stop at the , separator.
Parsing the csv file (or any file in general) with fscanf() is not recommended as it is very difficult to recover from errors and newlines are mostly indistinguishable from other white space characters. Furthermore, it is incorrect to use while (!feof(charge)) to run this loop.
You can learn Why is “while( !feof(file) )” always wrong? and you should tell you teacher about this. It is a common mistake to use feof() for this pupose.
You should instead read one line at a time with fgets() and use %nnn[^,] conversion specifiers to parse the character fields (nnn being the maximum field length).
Here is an example:
#include <errno.h>
#include <stdio.h>
#include <string.h>
int main() {
char buf[256];
char countryAux[100];
char nameDTAux[100];
char surnameDTAux[100];
char groupAux;
int actualscoreaux, faseActualaux;
... // declare team, lis...
FILE *chargue = fopen("Precharge.csv", "r");
if (chargue == NULL) {
fprintf(stderr, "cannot open %s: %s\n", "Precharge.csv",
strerror(errno));
return 1;
}
while (fgets(buf, sizeof buf, chargue)) {
if (sscanf(buf, "%99[^,],%99[^,],%99[^,], %c ,%d ,%d",
countryAux, nameDTAux, surnameDTAux,
&groupAux, &actualscoreaux,&faseActualaux) == 6) {
chargecountry(&team, countryAux);
chargenameDT(&team, surnameDTAux, nameDTAux);
chargeCapitan(&team, nameCapaux);
chargegropu(&team, groupAux);
chargeactualscore(&team, actualscoreaux);
chargeFase(&team, faseActualaux);
insert(lis, team);
forwards(lis);
} else {
printf("invalid record: %s", buf);
}
}
fclose(chargue);
return 0;
}
Today I decided to learn to code for the first time in my life. I decided to learn C. I have created a small program that checks a txt file for a specific value. If it finds that value then it will tell you that that specific value has been found.
What I would like to do is that I can put multiple files go through this program. I want this program to be able to scan all files in a folder for a specific string and display what files contain that string (basically a file index)
I just started today and I'm 15 years old so I don't know if my assumptions are correct on how this can be done and I'm sorry if it may sound stupid but I have been thinking of maybe creating a thread for every directory I put into this program and each thread individually runs that code on the single file and then it displays all the directories in which the string can be found.
I have been looking into threading but I don't quite understand it. Here's the working code for one file at a time. Does anyone know how to make this work as I want it?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
//searches for this string in a txt file
char searchforthis[200];
//file name to display at output
char ch, file_name[200];
FILE *fp;
//Asks for full directory of txt file (example: C:\users\...) and reads that file.
//fp is content of file
printf("Enter name of a file you wish to check:\n");
gets(file_name);
fp = fopen(file_name, "r"); // read mode
//If there's no data inside the file it displays following error message
if (fp == NULL)
{
perror("Error while opening the file.\n");
exit(EXIT_FAILURE);
}
//asks for string (what has to be searched)
printf("Enter what you want to search: \n");
scanf("%s", searchforthis);
char* p;
// Find first occurrence of searchforthis in fp
p = strstr(searchforthis, fp);
// Prints the result
if (p) {
printf("This Value was found in following file:\n%s", file_name);
} else
printf("This Value has not been found.\n");
fclose(fp);
return 0;
}
This line,
p = strstr(searchforthis, fp);
is wrong. strstr() is defined as, char *strstr(const char *haystack, const char *needle), no file pointers in it.
Forget about gets(), its prone to overflow, reference, Why is the gets function so dangerous that it should not be used?.
Your scanf("%s",...) is equally dangerous to using gets() as you don't limit the character to be read. Instead, you could re-format it as,
scanf("%199s", searchforthis); /* 199 characters + \0 to mark the end of the string */
Also check the return value of scanf() , in case an input error occurs, final code should look like this,
if (scanf("%199s", searchforthis) != 1)
{
exit(EXIT_FAILURE);
}
It is even better, if you use fgets() for this, though keep in mind that fgets() will also save the newline character in the buffer, you are going to have to strip it manually.
To actually perform checks on the file, you have to read the file line by line, by using a function like, fgets() or fscanf(), or POSIX getline() and then use strstr() on each line to determine if you have a match or not, something like this should work,
char *p;
char buff[500];
int flag = 0, lines = 1;
while (fgets(buff, sizeof(buff), fp) != NULL)
{
size_t len = strlen(buff); /* get the length of the string */
if (len > 0 && buff[len - 1] == '\n') /* check if the last character is the newline character */
{
buff[len - 1] = '\0'; /* place \0 in the place of \n */
}
p = strstr(buff, searchforthis);
if (p != NULL)
{
/* match - set flag to 1 */
flag = 1;
break;
}
}
if (flag == 0)
{
printf("This Value has not been found.\n");
}
else
{
printf("This Value was found in following file:\n%s", file_name);
}
flag is used to determine whether or not searchforthis exists in the file.
Side note, if the line contains more than 499 characters, you will need a larger buffer, or a different function, consider getline() for that case, or even a custom one reading character by character.
If you want to do this for multiple files, you have to place the whole process in a loop. For example,
for (int i = 0; i < 5; i++) /* this will execute 5 times */
{
printf("Enter name of a file you wish to check:\n");
...
}
Im very new to this language, can you help me:
Instead of making the user input col, row, and direction(scanf). I want to extract the data from file(format below)
From the file format i do not want to extract the first line(5,6), i only want to extract the remaining lines.
Below is a code of how to extract data from a file(using command line arguments), but this code extract the first line also, and only prints the lines.I do not want to print the line but to extract the data from a file instead of making the user input it.
File format:
colrow direction(starting from 2nd line)
5,6
A0 H
D0 V
C1 V
A4 H
F0 v
code of scanf
yourcolumn = getchar();
col = charToNum(yourcolumn); //function to input column
printf("enter row");
scanf("%d",&row);
printf("h: horizontally or v: vertically?\n");
scanf(" %c",&direction);
Code for extracting data from file:
#include <stdio.h>
int main(int argc, char* argv[])
{
char const* const fileName = argv[1]; /* should check that argc > 1 */
FILE* file = fopen(fileName, "r"); /* should check the result */
char line[256];
while (fgets(line, sizeof(line), file)) {
/* note that fgets don't strip the terminating \n, checking its
presence would allow to handle lines longer that sizeof(line) */
printf("%s", line);
}
/* may check feof here to make a difference between eof and io failure -- network
timeout for instance */
fclose(file);
return 0;
}
Since you are reading line-by-line, I suggest you restructure you file reading to match your logic
while (EOF != fscanf(file, "%[^\n]\n", line)) {
printf("> %s\n", line);
}
Is a way that one can read every line, one at a time. You can lookup the caveats of using fscanf and how to adjust the code to safely read without overflowing your line buffer.
Then, if you want to skip the first line, your code could look like this
if (EOF != fscanf(file, "%[^\n]\n", line)) {
// skip the first line
}
while (EOF != fscanf(file, "%[^\n]\n", line)) {
printf("> %s\n", line);
}
And your processing logic will look a lot like your mental process.
Yes, you could use a line counter, and only process if the counter is high enough; but, it is generally better to avoid introducing variables, if you can live without them. This is because an extra added variable doesn't make the code too hard to reason about; but, after you've repeated that "extra variable" rationale five or six times, the code quickly turns into something that's harder to maintain and harder to reason about. By the time you hit twenty or more extra variables, the odds of maintaining the code quickly without breaking it are lower.
Read the first line also with fgets() into a string and then scan the string for row, direction.
char line[256];
if (fgets(line, sizeof(line), file)) {
if (sscanf(line, "%d %c", &row, &direction) != 2) {
printf("Invalid first line '%s'\n", line);
} else {
while (fgets(line, sizeof(line), file)) {
printf("%s", line);
}
}
}
I'm sorry to do this kind of question (because there is so much on internet about that) but I have to ask this:
The exercise involve reading from a file with a list of students (a record contains: name, surname and serial number). I've already created the document and consist of 13 lines, but when I write on terminal ./a.out, the output is a list of 13 lines of this type: (null) (null) (null)
The code is:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define EOF (-1)
#define BUF 100
typedef struct stud{
char *surname;
char *name;
char *serial;
} student;
int main(void){
FILE *fd;
int n = BUF;
int k = 0;
int i = 0;
int ret;
char *s = malloc(BUF * sizeof(char));
if((fd = fopen("registry_office_students.txt","r")) == NULL){
perror("error opening file");
return -1;
}
while(fgets(s,n,fd)!=NULL){
k++;
}
student *a = malloc(k*sizeof(student));
rewind(fd);
ret = fscanf(fd, "%s, %s, %s", a[i].surname, a[i].name, a[i].serial);
while(fscanf(fd, "%s, %s, %s", a[i].surname, a[i].name, a[i].serial) == ret){
i++;
}
for(i=0;i<k;i++){
printf("%s, %s, %s \n", a[i].surname, a[i].name, a[i].serial);
}
fclose(fd);
return 0;
}
I apologize again and hope for a proper response, Thanks.
fscanf(3) with %s won't allocate any memory for a string. That string should already exist.
At least, replace
ret = fscanf(fd, "%s, %s, %s",
a[i].surname, a[i].name, a[i].serial);
with something like
{
char surname[48];
char name[64];
char serial[32];
memset (surname, 0, sizeof(surname));
memset (name, 0, sizeof(name));
memset (serial, 0, sizeof(serial));
memset (a+i, 0, sizeof(struct stud));
ret = fscanf(fd, "%47s, %63s, %31s", surname, name, serial);
if (ret==3) {
a[i].surname = strdup(surname);
if (!a[i].surname)
{ perror("strdup surname"); exit(EXIT_FAILURE); }
a[i].name = strdup(name);
if (!a[i].name)
{ perror("strdup name"); exit(EXIT_FAILURE); }
a[i].serial = strdup(serial);
if (!a[i].serial)
{ perror("strdup serial"); exit(EXIT_FAILURE); }
}
}
Notice that I am clearing memory before reading it. I am explicitly giving size of strings in format of fscanf. I am duplicating with a tested strdup the read strings into heap.
Actually, I believe your approach could be wrong. You might decide that each student should be on a single line, which you would read with getline(3) and parse with sscanf(3) (maybe %n would be useful!) or maybe strtok (or "manually" using isalpha)
Please, read more material about C programming, then compile with all warnings and debug info (gcc -Wall -g), learn to use the debugger (gdb) and the memory leak detector (valgrind).
Firstly, you never allocate memory for the strings stored inside your structs. I.e. your fscanf attempts to read data into buffers that don't exist.
Secondly, your reading code reads data into a[0] twice. I.e. the first fscanf will read the first record in a[0] and then the next fscanf will read the next record into a[0] again, overriding what was read previously. Why? Was that your intent (like skipping a table header or something like that)?
Thirdly, your counting code (fgets) is not the same as your reading code (fscanf). If the reading code fails prematurely for fscanf-specific reason, you will read less than k records. Yet your printing code prints all k of them unconditionally. (What if your reading code failed immediately due to some error in fscanf format? In that case you never read anything.)
Fourthly, each call to fgets in your counting code is limited by 100 characters or by a newline (that's how fgets works). This is completely non-synchronized with how fscanf works, which is not limited by anything in your case. This means that the number of records seen by the counting code might easily end up different (greater) than the number of records seen by the reading code.
I know this is a dumb question, but how would I load data from a multiline text file?
while (!feof(in)) {
fscanf(in,"%s %s %s \n",string1,string2,string3);
}
^^This is how I load data from a single line, and it works fine. I just have no clue how to load the same data from the second and third lines.
Again, I realize this is probably a dumb question.
Edit: Problem not solved. I have no idea how to read text from a file that's not on the first line. How would I do this? Sorry for the stupid question.
Try something like:
/edited/
char line[512]; // or however large you think these lines will be
in = fopen ("multilinefile.txt", "rt"); /* open the file for reading */
/* "rt" means open the file for reading text */
int cur_line = 0;
while(fgets(line, 512, in) != NULL) {
if (cur_line == 2) { // 3rd line
/* get a line, up to 512 chars from in. done if NULL */
sscanf (line, "%s %s %s \n",string1,string2,string3);
// now you should store or manipulate those strings
break;
}
cur_line++;
}
fclose(in); /* close the file */
or maybe even...
char line[512];
in = fopen ("multilinefile.txt", "rt"); /* open the file for reading */
fgets(line, 512, in); // throw out line one
fgets(line, 512, in); // on line 2
sscanf (line, "%s %s %s \n",string1,string2,string3); // line 2 is loaded into 'line'
// do stuff with line 2
fgets(line, 512, in); // on line 3
sscanf (line, "%s %s %s \n",string1,string2,string3); // line 3 is loaded into 'line'
// do stuff with line 3
fclose(in); // close file
Putting \n in a scanf format string has no different effect from a space. You should use fgets to get the line, then sscanf on the string itself.
This also allows for easier error recovery. If it were just a matter of matching the newline, you could use "%*[ \t]%*1[\n]" instead of " \n" at the end of the string. You should probably use %*[ \t] in place of all your spaces in that case, and check the return value from fscanf. Using fscanf directly on input is very difficult to get right (what happens if there are four words on a line? what happens if there are only two?) and I would recommend the fgets/sscanf solution.
Also, as Delan Azabani mentioned... it's not clear from this fragment whether you're not already doing so, but you have to either define space [e.g. in a large array or some dynamic structure with malloc] to store the entire dataset, or do all your processing inside the loop.
You should also be specifying how much space is available for each string in the format specifier. %s by itself in scanf is always a bug and may be a security vulnerability.
First off, you don't use feof() like that...it shows a probable Pascal background, either in your past or in your teacher's past.
For reading lines, you are best off using either POSIX 2008 (Linux) getline() or standard C fgets(). Either way, you try reading the line with the function, and stop when it indicates EOF:
while (fgets(buffer, sizeof(buffer), fp) != 0)
{
...use the line of data in buffer...
}
char *bufptr = 0;
size_t buflen = 0;
while (getline(&bufptr, &buflen, fp) != -1)
{
...use the line of data in bufptr...
}
free(bufptr);
To read multiple lines, you need to decide whether you need previous lines available as well. If not, a single string (character array) will do. If you need the previous lines, then you need to read into an array, possibly an array of dynamically allocated pointers.
Every time you call fscanf, it reads more values. The problem you have right now is that you're re-reading each line into the same variables, so in the end, the three variables have the last line's values. Try creating an array or other structure that can hold all the values you need.
The best way to do this is to use a two dimensional array and and just write each line into each element of the array. Here is an example reading from a .txt file of the poem Ozymandias:
int main() {
char line[15][255];
FILE * fpointer = fopen("ozymandias.txt", "rt");
for (int a = 0; a < 15; a++) {
fgets(line[a], 255, fpointer);
}
for (int b = 0; b < 15; b++) {
printf("%s", line[b]);
}
return 0;
This produces the poem output. Notice that the poem is 14 lines long, it is more difficult to print out a file whose length you do not know because reading a blank line will produce the output "x�oA". Another issue is if you check if the next line is null by writing
while (fgets(....) != NULL)) {
each line will be skipped. You could try going back a line each time to solve this but i think this solution is fine for all intents.
I have an even EASIER solution with no confusing snippets of puzzling methods (no offense to the above stated) here it is:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string line;//read the line
ifstream myfile ("MainMenu.txt"); // make sure to put this inside the project folder with all your .h and .cpp files
if (myfile.is_open())
{
while ( myfile.good() )
{
getline (myfile,line);
cout << line << endl;
}
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
Happy coding