reading data from a file after skiping the header - c

I'm trying to read numbers from a file, but first i gotta skip a header, this is a small code that only serves the purpose of testing the function, now...the function to skip part of the file works fine but when i try and read somthing from the file after i get a seg fault and the error code that means Status_acces_violation, but i just can't seem to find my mistake
The info in the file is always gonne be like this
Ex:
P5
256 789
125
125 236 789 ...(a bunch of numbers)
#include <ctype.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE *salt_header(FILE *poza){
char gunoi1[2];
fscanf(poza, "%s", gunoi1);
printf("%s\n", gunoi1);
int gunoi2;
fscanf(poza, "%d ", &gunoi2);
printf("%d ", gunoi2);
fscanf(poza, "%d", &gunoi2);
printf("%d\n", gunoi2);
fscanf(poza, "%d", &gunoi2);
printf("%d\n", gunoi2);
return poza;
}
int main()
{
FILE *poza;
char gunoi1[2], *nume;
nume = malloc(256 * sizeof(char *));
if(nume == NULL)
exit(-11);
scanf("%s", nume);
poza = fopen(nume, "r");
if(poza == NULL){
printf("Failed to open file\n");
exit(-1);
}
poza = salt_header(poza);
int numar;
for(int i = 0; i < 3; i++){
fscanf(poza, "%d", &numar);
printf("%d ", numar);
}
fclose(poza);
free(nume);
return 0;
}

char gunoi1[5]; // "P5" : 2 bytes , "\n" : 1 byte , "\0" : byte

just can't seem to find my mistake
In *scanf(), do not use "%s" without a width.
fscanf(poza, "%s", gunoi1); overflows char gunoi1[2]; as it is too small to store string "P5" leading to undefined behavior (UB). Remember a string always has a trailing null character, else it is not a string.
Also always check the return value of input functions.
A simple alternative, if the first line length is sane:
char buf[1000];
if (fgets(buf, sizeof buf, poza)) {
; // Successfully read the first line.
}

Related

How to fscanf only the elements that we want?

I want to do fscanf on a .txt file, here's how it looks
7 6
[1,2]="english"
[1,4]="linear"
[2,4]="calculus"
[3,1]="pe"
[3,3]="Programming"
I want to take only the 2 numbers in the brackets, the first is day, and the second is session, and I also want to take the string subject
Here's the whole code
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(){
FILE *inputFile, *outputFile;
int day;
int session;
char subject[15];
inputFile = fopen("Schedule.txt", "r");
if (inputFile == NULL) {
puts("File Schedule.txt Open Error.");
}
fscanf(inputFile, "%d %d %s", &day, &session, subject);
printf("%d", day);
fclose(inputFile);
return 0;
}
Apparently the fscanf does not work the way i want it to.
The expected output is storing the numbers to the variables I have assigned
What actually happened is it only printed out '7'
An approach reading line by line and using sscanf
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define LINEBUFSIZE 500
int main(){
FILE *inputFile;
char line[LINEBUFSIZE];
inputFile = fopen("Schedule.txt", "r");
if (inputFile == NULL) {
puts("File Schedule.txt Open Error.");
}
while (fgets(line, LINEBUFSIZE, inputFile)) {
int day;
int session;
char subject[15];
int r;
// %14s because char subject[15] (14 char + null)
r = sscanf(line, "[%d,%d]=%14s", &day, &session, subject);
if (r != 3)
// Could not read 3 elements
continue;
printf("%d %d %s\n", day, session, subject);
}
return 0;
}
to take only the 2 numbers in the brackets, the first is day, and the second is session, and I also want to take the string subject
(I leave OP to handle first line "7 6\n".)
Drop all fscanf() calls. Use fgets() to read a line and then parse.
char buf[100];
if (fgets(buf, sizeof buf, inputFile)) {
// Parse input like <[1,2]="english"\n>
int day;
int session;
char subject[15];
int n = 0;
sscanf(buf, " [%d ,%d ] = \"%14[^\"]\" %n",
&day, &session, subject, &n);
bool Success = n > 0 && buf[n] == '\0';
...
Scan the string. If entirely successful, n will be non-zero and buf[n] will pointer to the string's end.
" " Consume optional white spaces.
"[" Consume a [.
"%d" Consume optional spaces and then numeric text for an int.
"," Consume a ,.
"]" Consume a ].
"\"" Consume a double quote mark.
"%14[^\"]" Consume 1 to up to 14 non-double quote characters and form a string.
"%n" Save the offset of the scan as an int.

Read Line By Line Until Integer is Found C

Trying to create a program that takes in a text file and reads it line by line. It then finds the two integers that are on each line and adds them together. It then outputs the new line with the original string and total to a new text file. I need help adding the two integers, getting them from each line, and then putting the new line to a text file.
input text file
good morning hello 34 127
ann 20 45
10 11
fun program and you find the same 90 120
news paper said that 56 11
how do you like 20 5
line number 90 34
Outputs first like would look like: and then continue on
good morning hello 161
Code:
int processTextFile(char * inputFileName, char * outputFileName)
{
FILE *fp = fopen(inputFileName, "r");//open file to to read
char buff[1024];
char *p, *p1;
int num;
while (fgets(buff, 1024, fp)!=NULL)
{
printf("%s\n", buff);
while(scanf(buff, "%*[^0-9]%d", &num)== 1)
printf("%d\n", num);
//fscanf(fp, "%s", buff);
}
return 0;
}
EDIT!!!!::
So now that I've been able to accomplish this. How would I sort it by the number produced? for example:
Time is money 52
here I am 3
21
Would output to a new text file in order like
here I am 3
21
Time is money 52
My version using strcspn() is supposed to work with stdin for input and stdout for output. (so you can do executable <textfile >newtextfile)
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char line[1000];
while (fgets(line, sizeof line, stdin)) {
char *ptr;
size_t x = strcspn(line, "0123456789");
if (line[x]) {
errno = 0;
int n1 = strtol(line + x, &ptr, 10);
if (*ptr && !errno) {
errno = 0;
int n2 = strtol(ptr, &ptr, 10);
if (*ptr && !errno) {
int n3 = n1 + n2;
printf("%.*s%d\n", (int)x, line, n3);
} else {
printf("%s", line); // line includes ENTER
}
} else {
printf("%s", line); // line includes ENTER
}
} else {
printf("%s", line); // line includes ENTER
}
}
return 0;
}
The same version without the error checking
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char line[1000];
while (fgets(line, sizeof line, stdin)) {
char *ptr;
size_t x = strcspn(line, "0123456789");
int n1 = strtol(line + x, &ptr, 10);
int n2 = strtol(ptr, &ptr, 10);
int n3 = n1 + n2;
printf("%.*s%d\n", (int)x, line, n3);
}
return 0;
}
The approach should be:
open two files, one for input, one for output.
use sscanf() to read the input buffer.
scan the leading string, and then two number.
if previous sscanf() fails, only check for two number.
if either of the above scanning is success, print the sum to the output file.
A sample code, should look like
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
FILE *fpin = fopen("ipfile", "r");//open file to to read
if (!fpin)
{
printf("Error in ipfile opening\n");
exit (-1);
}
FILE *fpout = fopen("opfile", "w");//open file to to write
if (!fpout)
{
printf("Error in opfile opening\n");
exit (-1);
}
char buff[1024] = {0};
char str[1024] = {0};
int num1 =0, num2= 0;
while (fgets(buff, 1024, fpin)!=NULL)
{
memset(str, 0, sizeof(str));
//printf("%s\n", buff);
if(sscanf(buff, "%[^0-9]%d %d", str, &num1, &num2)== 3)
fprintf(fpout, "%s %d\n", str, (num1+num2));
else if (sscanf(buff, "%d %d", &num1, &num2)== 2)
fprintf(fpout, "%d\n", (num1+num2));
}
return 0;
}
Note:
The above procedure, is a kind of workaround. If the data pattern in the file changes, lot of changes will be required to maintain a code like that. Instead of usinf sscnaf(), for a better and roubust approach, you should
read the line from file
start tokenizing the input buffer (strtok()) and check for ints as tokens (strtol()).
save the returned tokens and ints seperately.
once the strtok() returns NULL, you print the string tokens and the sum of the ints to the o/p file.
I intend not to change your code completely, so I just added some snippets for improvement.
int processTextFile(char *inputFileName, char *outputFileName) {
FILE *fp = fopen(inputFileName, "r");
FILE *out = fopen(outputFileName, "w");
char line[1024];
if (!fp) {
perror(inputFileName);
return;
}
while (fgets(line, sizeof(line), fp) != NULL) {
int num1 = 0, num2 = 0;
char textPart[1024] = "";
if ( !sscanf(line, "%[a-zA-Z' ']%d%d", textPart, &num1, &num2) {
sscanf(line, "%d%d", &num1, &num2);
}
fprintf(out, "%s %d\n", textPart, num1 + num2);
}
fclose(fp);
fclose(out);
}
Explanation:
I scanned the text file, extracted the text part and the two ints. Since I noticed that the ints are placed at the end of each line, I just used sscanf() for that matter.
sscanf(line, "%[a-zA-Z' ']%d%d", textPart, &num1, &num2);
Here, "%[a-zA-Z' ']%d%d" format specifiers means to get only alphabets and spaces.
Since it will only get letters and spaces, the line "10 11" in your input file won't be put to num1 and num2. Because the code inspects first for a string containing letters and spaces. Since 10 and 11 are not of the qualified types, then the line is just skipped.
That's why I added an if-else statement, which checks if sscanf wrote anything to memory. If sscanf returned 0, then it means that no text part is present. Just digits. So the program will scan the two digits.
if ( !sscanf(line, "%[a-zA-Z' ']%d%d", textPart, &num1, &num2) ) {
sscanf(line, "%d%d", &num1, &num2);
}
I also added file checking for input file. It checks if file doesn't exist or can't be opened by the filestream.
if (!fp) {
perror(inputFileName);
return;
}
Here is the content of output file after execution:
good morning hello 161
ann 65
21
fun program and you find the same 210
news paper said that 67
how do you like 25
line number 124

While looping to end of file?

#include <stdio.h>
#include <stdlib.h>
//#define true 0
typedef struct
{
char currency[8];
int exchangerate;
} randT;
void main()
{
int i, num;
char currency1[8], ch;
FILE *file = fopen("address", "r");
randT name[7];
while(fscanf(file, "%i", &name[i].exchangerate) != EOF)/*I think this is where my problem is*/
{
fscanf(file, "%s %i", &name[i].currency, &name[i].exchangerate);
//printf("%s %i\n", currency1, num);
//if (fscanf(file, "%i", &currency1) == EOF) break;
printf("%s %i\n", name[i].currency, name[i].exchangerate);
i++;
}
fclose(file);
}
It is giving segmentation fault(core dumped) and i am fairly new to the fscanf functions and such. Please help!
my text file looks like this:
jeff 4
jina 5
jeffrey 6
jinna 7
jeffu 8
jinina 9
jeffz 10
The cause of the crash is that you need to initialize int i = 0;. As you have it, i is indeterminate, so probably name[i] is a massively out-of-bounds access.
For the fscanf, you have mostly the right idea about the loop, except instead of checking != EOF it's better to check == 1 or however many items you were reading. If the file contains something that can't be processed as a number, then fscanf will not return EOF.
However this is not the right way to read your particular file. You read %i then %s %i every time around, but your file only contains a string and an int. Change to:
while ( 2 == fscanf(file, "%7s %i", name[i].currency, &name[i].exchangerate) )
Also after doing i++ you need to check that i has not gone out of bounds (i.e. it's less than 7).
Note that name[i].currency decays to pointer to char - you shouldn't put & on it. Also you should use the length specifier to avoid running over the end of the array.
I would use the loop structure:
for (num_read = 0; num_read < sizeof name / sizeof name[0]; ++num_read)
{
if ( 2 != fscanf(file,.....
break;
printf(....
}

How to read and store 2 float values seperated by a comma from a file into two arrays where each float is stored in one array

my text file format is this:
3.2 , 5.6
444.2 , 555
112.34 , 32.3
i want to read the above information present within file name file.txt and store it in two arrays a,b where a will have the float value before the comma and b will have the float value after the comma
Use fgets() in a loop to read each line. Then once you have the line, use sscanf() to scan out the two floating-point numbers, like so:
while(fgets(line, sizeof line, myfile) != NULL)
{
if(sscanf(line, "%f,%f", &a[i], &b[i]) == 2)
{
++i;
}
else
printf("Parse error in %s", line);
}
Note that the return value from sscanf() says how many conversions that succeeded. If it isn't two, we don't want to move forward in the array. Remember to make sure i is initialized to 0 before the loop, of course.
E.g.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define DATA_SIZE 10
int main (void){
char filename[256] = "file.txt";
char input_line[128];
FILE *fp;
float a[DATA_SIZE], b[DATA_SIZE];
int i,j;
if(NULL==(fp=fopen(filename, "r"))){
perror("input file open");
return -1;
}
i=0;
while(NULL!=fgets(input_line, sizeof(input_line), fp)){
if(*input_line == '\n') continue;
a[i]=atof(strtok(input_line, " ,\n"));//ok even this ","
b[i]=atof(strtok(NULL , " ,\n"));
++i;
}
//check print
for(j=0;j<i;++j){
printf("a[%d]=%g, b[%d]=%g\n", j, a[j], j, b[j]);
}
return 0;
}

FILE IO Trouble

I am having trouble with some file IO stuff.
I have this file:
db.dat:
Ryan
12 69.00 30.00 0.00
Bindy Lee
25 120.00 89.00 1.00
And this is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define RECORDS 30
#define LEN 20
main()
{
FILE *fptr;
fptr = fopen("db.dat", "r");
int i;
int counter = 2;
for (i = 0; i < counter; i++)
{
char temp1[LEN];
char temp2[LEN + 10];
fgets(temp1, LEN, fptr);
fgets(temp2, LEN, fptr);
printf("%s %s", temp1, temp2);
}
fclose(fptr);
}
I am supposed to get both lines, but I am getting this instead:
Ryan
12 69.00 30.00 0.00
Bindy Lee
Can someone please help! I don't know why I am not getting both lines, and why I am getting spaces. Very odd...Thanks!!!!
fgets stops after it reads LEN characters OR reaches the end of the line. I think your problem here is that you made LEN too small.
Change your printf to something more verbose like printf("temp1='%s'\ntemp2='%s'\n", temp1, temp2); and you should be able to see what was actually read into each string.
For the additional " ":
change:
printf("%s %s", temp1, temp2);
to
printf("%s%s", temp1, temp2);
Since the string has already contained the '\n'.
Reference:
A newline character makes fgets stop reading, but it is considered a valid
character and therefore it is included in the string copied to str.
You are only reading 40 bytes. If you increase the LEN you can read the remaining line,
Or instead of reading by number of bytes, you could read the entire line until there is a new line
#include <string.h>
#define RECORDS 30
#define LEN 20
main()
{
FILE *fptr;
fptr = fopen("b.db", "r");
int i;
int counter = 4;
for (i = 0; i < counter; i++)
{
char temp1[LEN];
fscanf(fptr, "%[^\n]%*c", temp1);
printf("%s\n", temp1);
}
fclose(fptr);
}
If you are interested in reading name and his corresponding record at the same time you could tweak something like,
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define RECORDS 30
#define LEN 20
main()
{
FILE *fptr;
fptr = fopen("b.db", "r");
int i;
int counter = 2;
for (i = 0; i < counter; i++)
{
char temp1[LEN];
char temp2[RECORDS];
fscanf(fptr, "%[^\n]%*c%[^\n]%*c", temp1, temp2);
printf("%s ---- %s\n", temp1, temp2);
}
fclose(fptr);
}
Given that you're taking structured input, you might consider using scanf instead of fgets. It isn't clear to me what you're saying with "I am supposed to get both lines".
Code that should work better for this would be something like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define RECORDS 30
#define LEN 20
main()
{
FILE *fptr;
fptr = fopen("db.dat", "r");
int i;
int counter = 3;
for (i = 0; i < counter; i++)
{
char temp1[LEN];
char temp2[LEN + 10];
fgets(temp1, LEN, fptr);
fgets(temp2, LEN, fptr);
printf("%s%s", temp1, temp2);
}
fclose(fptr);
}
The biggest thing is you weren't reading the last line and you didn't need the space between the "%s %s" in the printf statement. "%s%s" should work fine.
I have a try, and debug; I find the problem just like what missingno said:
"fgets stops after it reads LEN characters OR reaches the end of the line. I think your problem here is that you made LEN too small."
the first time (count = 0), temp2 does not get the '\n';
the second time (count = 0), temp1 get the '\n';
this is why, you can have a try and debug your code.....

Resources