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.....
Related
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.
}
The wordlist.txt is including like:
able
army
bird
boring
sing
song
And I want to use fscanf() to read this txt file line by line and store them into a string array by indexed every word like this:
src = [able army bird boring sing song]
where src[0]= "able", src[1] = "army" and so on. But my code only outputs src[0] = "a", src[1] = "b"... Could someone help me figure out what's going wrong in my code:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
FILE *fp = fopen("wordlist.txt", "r");
if (fp == NULL)
{
printf("%s", "File open error");
return 0;
}
char src[1000];
for (int i = 0; i < sizeof(src); i++)
{
fscanf(fp, "%[^EOF]", &src[i]);
}
fclose(fp);
printf("%c", src[0]);
getchar();
return 0;
}
Pretty appreciated!
For example like this.
#include <stdio.h>
#include <string.h>
#include <errno.h>
#define MAX_ARRAY_SIZE 1000
#define MAX_STRING_SIZE 100
int main(int argc, char *argv[]) {
FILE *fp = fopen("wordlist.txt", "r");
if (fp == NULL) {
printf("File open error\n");
return 1;
}
char arr[MAX_ARRAY_SIZE][MAX_STRING_SIZE];
int index = 0;
while (1) {
int ret = fscanf(fp, "%s", arr[index]);
if (ret == EOF) break;
++index;
if (index == MAX_ARRAY_SIZE) break;
}
fclose(fp);
for (int i = 0; i < index; ++i) {
printf("%s\n", arr[i]);
}
getchar();
return 0;
}
Some notes:
If there is an error, it is better to return 1 and not 0, for 0 means successful execution.
For a char array, you use a pointer. For a string array, you use a double pointer. A bit tricky to get used to them, but they are handy.
Also, a check of the return value of the fscanf would be great.
For fixed size arrays, it is useful to define the sizes using #define so that it is easier to change later if you use it multiple times in the code.
It's reading file one character at a time, Which itself is 4 in size like we see sizeof('a') in word able. Same goes for 'b' and so on. So one approach you can use is to keep checking when there is a space or newline character so that we can save the data before these two things as a word and then combine these small arrays by adding spaces in between and concatenating them to get a single array.
This is part of a project that i'm doing. Essentially i want to read a text file called "Circuit" that has this inside:
Circuit title example
V1 1 0 24
V2 3 0 15
R1 1 2 10000
R2 2 3 8100
R3 2 0 4700
To give you some context, the values represent a circuit like this:
Circuit example
I made a code to save all these values in a structure and printed them out to see if they were being saved correctly.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct
{
char type, name, noMaior, noMenor;
int value;
}line;
int main(void)
{
line ramo[10];
FILE *ficheiro;
int i = 0, j;
char titulo[200];
if ((ficheiro = fopen("circuit.txt", "r")) == NULL)
printf("Error opening file!");
fgets(titulo, 199, ficheiro);
printf("%s", titulo);
while ((fscanf(ficheiro, "%c%c %c %c %d\n", &ramo[i].type, &ramo[i].name, &ramo[i].noMaior, &ramo[i].noMenor, &ramo[i].value)) != EOF)
{
i++;
//if (fgetc(ficheiro)=='.')
// break;
}
fclose(ficheiro);
for (j = 0; j < i; j++)
printf("%c%c %c %c %d\n", ramo[j].type, ramo[j].name, ramo[j].noMaior, ramo[j].noMenor, ramo[j].value);
return 0;
}
It outputs the same text that is in the file, which is what i intended. Now here comes the tricky part, we have to put ".end" or ".END" in the end of our file, so i made those two commented lines to scan the file for a dot and stop reading it if it encounters one but it causes me some problems when saving the values to the structure. This is what i get as an output:
Circuit title example
V1 1 0 24
2 3 0 15
1 1 2 10000
2 2 3 8100
3 2 0 4700
The "break" works as intended, because if i put a dot in the middle of the file it will stop reading whatever comes after but sadly it is ignoring the first letter and according to the debug tool it is saving a ' ' (a space) in the place of the letters (ramo[].type). I tried to learn as much as i could about the behaviours of fscanf and fgetc but i can't draw any conclusion as to why this is happening.
PS: tried to translate some of the variables to make it easier to read but some are still in portuguese, like "ficheiro"=file. Also take it easy on me folks, i just started learning coding!
Use fgets to read each line from the file. Then you can check for a dot or use strncmp or strcmp to test for specific values. If the value is not detected, parse the line using sscanf.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct
{
char type, name, noMaior, noMenor;
int value;
}line;
int main(void)
{
line ramo[10];
FILE *ficheiro;
int i = 0, j;
char titulo[200];
char input[200];
if ((ficheiro = fopen("circuit.txt", "r")) == NULL)
printf("Error opening file!");
fgets(titulo, sizeof titulo, ficheiro);
printf("%s", titulo);
while ( fgets ( input, sizeof input, ficheiro))
{
if ( '.' == input[0]) {//test for a dot at start of line
break;
}
else {
if (( 5 == sscanf(input, "%c%c %c %c %d"
, &ramo[i].type, &ramo[i].name, &ramo[i].noMaior, &ramo[i].noMenor, &ramo[i].value))) {
i++;
}
}
}
fclose(ficheiro);
for (j = 0; j < i; j++)
printf("%c%c %c %c %d\n", ramo[j].type, ramo[j].name, ramo[j].noMaior, ramo[j].noMenor, ramo[j].value);
return 0;
}
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
this might look familiar, but am having different problems come up, so I'm trying to ask a different question. My assignment is to read in a file like so:
AACTGGTGCAGATACTGTTGA
3
AACTGGTGCAGATACTGCAGA
CAGTTTAGAG
CATCATCATCATCATCATCAT
The first line is the original line I will testing the following ones against, with the second line giving the number of remaining lines. When I run the following code, it prints out my entire input file, but to the first index. So while I need each line to be a separate index to be able to call them, it isn't working out.
I assume I'm going wrong by having the defined LENGTH and ROW so big, but am unsure of any other way to save it line by line, especially since it is mixed (chars with a line of int in between). My problem here is also that I have no prior knowledge given of how long either the rows of "DNA" will be nor how many lines total.
For what it's worth: I was advised a few things but am still unsure how to literally implement them.
One of these was to first use fscanf with %s for the first line, then fscanf with %d for the second, and a loop of fscanf %s for the remaining lines. I've tried doing that, but couldn't get that to work properly either.
The second way I was given was "fgets() for the first line, fscanf() + fgetc() for the second line, and then a loop of fgets() for everything that remains." Again, I am unsure of how to implement this exactly.
Please and thank you!
Here's my code so far:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define LENGTH 125
#define ROW 125
struct dna{
char code [LENGTH];
};
int main(){
char filename[] = "input1.txt";
FILE *input = fopen("input1.txt","r");
char firstDna[LENGTH][ROW]={""};
int n=0,i=0,j;
makeArray(input,firstDna);
//closing file
fclose(input);
system("pause");
return 0;
}
void makeArray(FILE *input,char firstDna[LENGTH][ROW]){
int i,j;
for(i = 0; i < LENGTH; i++){
for(j =0; j < ROW; j++){
fscanf(input,"%c",&firstDna[i][j]);
printf("%c", firstDna[i][j]);
i++;
}
}printf("\n\n\n");
}
I implemented the first "advise" that you mentioned, fscanf with %s for the first line and fscnanf with %d for the second ...
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define LENGTH 125
#define ROW 125
struct dna{
char code [LENGTH];
};
void makeArray(FILE *input,char firstDna[LENGTH][ROW])
{
int i;
int remaining_lines;
fscanf(input,"%s\n",firstDna[0]);
printf("%s\n", firstDna[0]);
//scanning the number of remaing_lines
fscanf(input,"%d\n",&remaining_lines);
for(i = 1; i < LENGTH && i <= remaining_lines; i++)
{
fscanf(input,"%s\n",firstDna[i]);
printf("%s\n", firstDna[i]);
}
}
int main(){
char filename[] = "input1.txt";
FILE *input = fopen(filename,"r");
char firstDna[LENGTH][ROW];
makeArray(input,firstDna);
//closing file
fclose(input);
system("pause");
return 0;
}
hope this helps