C reading a file of binary numbers drops first char - arrays

Can anyone help me understand why the first char read from the file is dropped when I increase the file size to be > 19 rows?
When I run this with < 20 rows it works perfect, reads the input and dumps it. when I add a 20th row the first row of input drops the leading char when I print the array.
Im lost. :)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main () {
int i, j = 0;
FILE *pFile;
char string[20][12];
char file_contents_resultset[20][12];
pFile = fopen("sonar.txt", "r");
if (pFile == NULL)
{
printf ("error opening file");
return 0;
}
// Load 20 row of input into in an array and store a copy
for (i = 0; i < 20; i++)
{
fscanf (pFile, "%12s", &string[i]);
strcpy (file_contents_resultset[i], string[i]);
}
//Dump the first 5 rows of the array
printf ("Dump array contents \n");
for (i = 0; i < 5; i++)
{
for (j = 0; j < 12; j++)
{
printf ("%c", file_contents_resultset[i][j]);
}
printf ("\n");
}
fclose (pFile);
return 0;
};
This is my input file.
000110010001
101000110000
000110010111
100011100010
111001100001
001010001010
010100100101
011000010000
111111011010
001111011101
011011010010
001100010101
001010101100
000000000000
100010111111
100100110011
111100100001
011110001110
000110100101
011101111001
and this is the output
Dump array contents
00110010001
101000110000
000110010111
100011100010
111001100001
and this is the output if I delete the 20th row of input in the input file. Note the first char is no longer dropped.
Dump array contents
000110010001
101000110000
000110010111
100011100010
111001100001

Your one of the arrays you use for reading is redundant. You can use only string[][] or only file_contents_resultset[][].
I found that your problem is in the strcpy() call. Reading from the buffer is fine, but strcpy() seems to copy a blank character in the memory location of file_contents_resultset[0][0].
So to fix it by keeping as much of the program intact i did:
// ...
// stores only one row at a time
char string[12];
// ...
for (int i = 0; i < 20; i++) {
fscanf(pFile, "%12s", &string);
strcpy(file_contents_resultset[i], string);
}
// ...
}
If you want to be more concise and save memory, you can remove string altogether and just write:
// ...
// char string[12];
char file_contents_resultset[20][12];
// ...
// brackets in loops and other blocks can be omitted
// if the block is just 1 line long.
for (int i = 0; i < 20; i++)
fscanf(pFile, "%12s", &file_contents_resultset[20][12]);
// ...

Related

How to read all characters from file and store it in 2d array without \n?

I am trying to read a file and store each of its character in 2d array(of size 7 by 7) without special characters like '\n' and than print that 2d array.
I write a code but it does not store and print the last line characters in 2d array.
#include<stdio.h>
#include<stdlib.h>
int main()
{
char ar[7][7],c;
int i,j;
FILE *fp;
fp=fopen("B11.txt","r");
if(fp==NULL)
printf("File not Found");
for(i=0; i<7; i++)
{
for(j=0; j<7; j++)
{
fscanf(fp,"%c",&ar[i][j]);
}
}
for(i=0; i<7; i++)
{
for(j=0; j<7; j++)
{
printf("%c",ar[i][j]);
}
}
fclose(fp);
}
This the output of the my code:
abtvelo
camerag
bhtollp
qeryvxq
appboyl
awerfgh
But the file contains,
abtvelo
camerag
bhtollp
qeryvxq
appboyl
awerfgh
comsats
Here the file contains the word 'comsats' also, that is not printed. Why this word comsats is not printed?
for(i=0; i<7; i++)
{
for(j=0; j<7; j++)
{
fscanf(fp,"%c",&ar[i][j]);
}
}
ar[i][0] will have \n left out from previous line summing up to 7 \n thus ignoring last line.
change to
fscanf(fp," %c",&ar[i][j]);
or
have getchar() after inner for loop.
The \n character is causing the last line to be skipped.
Change this:
fscanf(fp,"%c",&ar[i][j]);
To this:
fscanf(fp," %c",&ar[i][j]);
^
The space consumes the newline character when using scanf() format specifiers such as %c %lf %d etc. The space is not needed however for reading strings, ( %s ).
Regarding your statement: without special characters like '\n'
If by this you are referring characters such as:
space (" ")
horizontal tab ("\t")
formfeed ("\f")
carriage return ("\r")
vertical tab ("\v")
and of course newline ("\n")
Consider replacing the fscanf() construct with one using fgetc() in conjunction with the white-space test function: isspace(). (which checks for those characters listed above.) Example:
#define ROW 7
#define COL 7
int main(void)
{
int row = 0;
int col = 0;
char ar[COL][ROW];
int byte;
FILE *fp = fopen(filename, "r");
if(fp)
{
byte = fgetc(fp);
while(byte != EOF)
{
if(!isspace(byte))
{ //populate array only if not white-space
ar[col][row++] = (char)byte;
if(row == ROW)
{
row = 0;
col++;
}
if(col == COL) break;
}
byte = fgetc(fp);
}
fclose(fp);
}
// print results as in your original post...
return 0;
}

How to input two strings separated by new line in C

How can I input 2 strings which are separated by a new line?
My Problem:
First I need to give how many strings I need to get and then I need to get those strings then display it.
I tried this:
Code:
#include <stdio.h>
#include <string.h>
int main()
{
int n,i = 0;
scanf("%d", &n);
char arr[n][100];
for(int i = 0; i < n; i++)
{
scanf("%[^\n]s", arr[i]);
}
for(int i = 0; i < n; i++)
{
printf("%s\n", arr[i]);
}
return 0;
}
My Input is :
2 I am
Aravind
My Output is:
I am
รพ
First Line I got correct one but second line it shows some garbage value. Help me to solve this.
You have two major problems:
The "%[" format ends with the closing "]", there should be no "s" at the end.
The "%[" format doesn't skip leading space, like that newline which will be present after the first line you read.
Both these issues can be easily solve by using fgets to read whole lines instead.
You already have suggestions to not use scanf. However, if you 'must' use scanf then you can consider the following approach:
For dynamic memory allocation you should use malloc
the newline character stays in the stdin and hence needs to be flushed or handled/ignored
Here is the updated code.
int main()
{
int n,i = 0;
scanf("%d", &n);
scanf("%*[\n]");
/*this will read the \n in stdin and not store it anywhere. So the next call to
* scanf will not be interfered with */
char **inputs;
inputs = malloc(n * sizeof(char *));
for (i = 0; i < n; i++)
{
inputs[i] = malloc(100 * sizeof(char));
}
for(i = 0; i < n; i++)
{
scanf("%*[\n]");
scanf("%100[^\n]", inputs[i]);
}
for(i = 0; i < n; i++)
{
printf("%s\n", inputs[i]);
}
return 0;
}
use gets(arr[i]) instead of scanf.

read a file and save as a matrix

i have a file like that :
1 100
2 200
3 300
4 400
1
i want to save it as a matrix and i want to save NULL if there is no second number !
i tried to write the program but it does not work correctly !
#include<stdio.h>
int main() {
int k=0 ,i,j , arr[100][100];
FILE *in= fopen("file.txt","r");
char line[1000];
while(fgets(line,1000,in) !=NULL) k++;
fgets(line,1000,in);
for (i=0;i<k;i++){
for (j=0;j<2;j++){
int tmp ;
fscanf(in ,"%d", &tmp) ;
arr[i][j] = tmp ;
}
}
fclose(in);
return 0; }
Two major problems:
The first is that the first loop will read all lines, even the one with the single number on the line. That means the lonely fgets call will not do anything, and more importantly that the value of k will be wrong.
The second problem is that once you read all data from the file, you don't go back to the beginning of the file, instead you continue to try and read from beyond the end of the file.
The first problem can be solve by skipping the second fgets call, and decreasing k by one.
The second problem can be solved by calling rewind after you counted the number of lines.
Also when you actually read the numbers, you don't need the inner loop, just do e.g.
scanf("%d %d", &arr[i][0], &arr[i][1]);
Actually, you don't need the first line-counting loop at all, you can do it all in a single loop, by using fgets and sscanf and then checking the return value of sscanf. So your program could look something like
#include <stdio.h>
int main(void)
{
int values[100][2];
FILE *input = fopen("file.txt", "r");
size_t entries = 0;
if (input != NULL)
{
char buffer[40];
while (fgets(buffer, sizeof(buffer), input) != NULL && entries < 100)
{
int res = sscanf(buffer, "%d %d", &values[entries][0], &values[entries][1]);
if (res <= 1 || res == EOF)
{
// Read the last line with only one number, or an error happened
values[entries][0] = 0;
values[entries][1] = 0;
break;
}
++entries;
}
if (ferror(input))
{
printf("Error reading file\n");
}
fclose(input);
}
// All done, the number of "records" or "entries" is in the variable entries
// Example code: print the values
for (size_t i = 0; i < entries; ++i)
printf("Line %d: %d %d\n", i + 1, values[i][0], values[i][1]);
return 0;
}

Why is this array script not printing right results?

I have a textfile of numbers written in words, with spaces between like..
zero three five two one .. etc there are 3018 words in total.
This is my code:
#include <stdio.h>
int main(void)
{
int i = 0;
int d = 0;
int j = 0;
char array[9054][5];
char hi[9054];
FILE *in_file;
in_file = fopen("message.txt", "r");
while (!feof(in_file))
{
fscanf(in_file, "%s", array[i]);
i++;
}
printf(array[9049]);
while (1);
return 0;
}
so the 9049th worth in my textfile is the number three.. but when I run this script, it prints "threethreezero"instead?? i thought the fscanf ignored whitespace (spaces) so why does accept another three and zero into this string?
OP figured things out with the help of comments, so here is a cumulative fix.
#include <stdio.h>
int main(void)
{
int i = 0;
int d = 0;
int j = 0;
// Make room for the null character
char array[9054][5+1];
char hi[9054];
FILE *in_file;
in_file = fopen("message.txt", "r");
//check `fscanf()`'s return value rather than using feof()
// Limit input put with 5
while (fscanf(in_file, "%5s", array[i]) == 1);
i++;
}
// Check that code read enough input
if (i >= 9049) {
// Do not use `printf()` on uncontrolled strings that may contain %
fputs(array[9049], stdout);
} else {
puts("Oops");
}
while (1);
return 0;
}

handling trailing \n when using feof()

I have written a small program which takes input of a file such as:
13,22,13,14,31,22, 3, 1,12,10
11, 4,23, 7, 5, 1, 9,33,11,10
40,19,17,23, 2,43,35,21, 4,34
30,25,16,12,11, 9,87,45, 3, 1
1,2,3,4,5,6,7,8,9,10
and outputs the largest sum of numbers on each line that is less than 50.
However if the inputted file has a trailing newline character the loop runs one too many times and hence another line is added to the array with random data. So I'm looking for a better way to do this comparison to avoid this issue. I'm also assuming all lines have 10 integers on at the moment as i cannot think of a better way to do the end of line loop comparison.
#include <stdio.h>
#include <stdlib.h>
void readLineData(int lineNo, int val[][10], FILE *fp);
int findSum(int lineNo, int val[][10], FILE *fp);
int main(int argc, char *argv[]) {
FILE *fp;
int val[5][10];
// Open file.
if ((fp = fopen(argv[1], "r")) == NULL)
{
perror("Cannot open file ");
exit(EXIT_FAILURE);
}
for (int i = 0; !feof(fp); i++) // runs too many times if file ends with '\n'
{
readLineData(i, val, fp);
printf("%d\n", findSum(i, val, fp));
}
fclose(fp);
return EXIT_SUCCESS;
}
void readLineData(int lineNo, int val[][10], FILE *fp) {
char c;
for (int i = 0; i < 10; i++) // assuming line contains 10 integers
{
fscanf(fp, "%d,", &val[lineNo][i]);
}
}
int findSum(int lineNo, int val[][10], FILE *fp) {
int highVal = 0;
int value1 = 0;
int value2 = 0;
for(int i = 0; i < 10; i++) //each letter
{
for(int j = 0; j < 10; j++)// every other letter
{
if((val[lineNo][i] + val[lineNo][j]) > highVal && i != j && (val[lineNo][i] + val[lineNo][j]) <= 50)
{
highVal = val[lineNo][i] + val[lineNo][j];
value1 = val[lineNo][i];
value2 = val[lineNo][j];
}
}
}
printf("Line %d: largest pair is %d and %d, with a total of: ", lineNo+1, value1, value2);
return highVal;
}
any help with those loop comparisons and general notation tips is most welcome.
Thanks
The posted code does not distinguish between two lines that have five integers and (the expected) one line that has 10 integers. Suggest reading in a line at a time, using fgets() and then using sscanf() on the read line to ensure that all the read integers belong to the same line.
Check the return value of input operations. For example, sscanf() (and fscanf()) return the number of assignments made. Only process lines that have the expected 10 integers, which would detect invalid lines including the trailing empty line.
For example:
/* Returns 1 on success and 0 on failure. */
int readLineData(int lineNo, int val[][10], FILE *fp)
{
char line[1024]; /* Arbitrarily large. */
if (fgets(line, sizeof(line), fp))
{
/* %n records position where processing ended. */
int pos;
const int result = sscanf(line,
"%d,%d,%d,%d,%d,%d,%d,%d,%d,%d%n",
&val[lineNo][0],
&val[lineNo][1],
&val[lineNo][2],
&val[lineNo][3],
&val[lineNo][4],
&val[lineNo][5],
&val[lineNo][6],
&val[lineNo][7],
&val[lineNo][8],
&val[lineNo][9],
&pos);
/* 10 integers and full line processed,
except if new-line character present. */
return 10 == result &&
(pos == strlen(line) ||
(pos + 1 == strlen(line) && '\n' == line[pos]));
}
return 0;
}
You could simply consume the newline character yourself:
for (int i = 0; !feof(fp); i++) // runs too many times if file ends with '\n'
{
readLineData(i, val, fp);
printf("%d\n", findSum(i, val, fp));
fscanf(fp, "%*c"); // read a character without storing it in a variable
}
Note that there are undoubtedly better ways that involve reading an entire line at once and simply examining its contents; but this is the easiest way that will fit with what you already have.
you could check if fscanf fails in your readLineData function:
int readLineData(int lineNo, int val[][10], FILE *fp) {
for (int i = 0; i < 10; i++) {// assuming line contains 10 integers
if (fscanf(fp, "%d,", &val[lineNo][i]) != 1) {
return 1;
}
}
return 0;
}

Resources