Reading random input from file - c

I have a file and I want to read some random input from file, I don't want to use getline or some things like that, the scanning works but it reads some random stuff, like null or different characters. I think the problem could be when i am reading a single character and that might destroy all this.
Here is some code to see what I did:
#include <stdio.h>
#include <stdlib.h>
typedef struct queries
{
char type;
int node;
char *addr;
} Queries;
int main()
{
int i;
FILE *f;
f = fopen("queries.in", "r");
if (!f)
{
fprintf(stderr, "File queries.in was not opened correctly.\n");
exit(1);
}
int n_queries;
fscanf(f, "%d\n", &n_queries);
Queries *q = (Queries*)malloc(n_queries*sizeof(struct queries));
for (i = 0; i < n_queries; ++i)
{
fscanf(f, "%c ", &q[i].type);
if(q[i].type == 'q') fscanf(f, "%d %s\n", &q[i].node, q[i].addr);
else fscanf(f, "%d\n", &q[i].node);
}
for (i = 0; i < n_queries; ++i)
{
printf("%d %c ", i, q[i].type);
if(q[i].type == 'q') printf("%d %s\n", q[i].node, q[i].addr);
else printf("%d\n", q[i].node);
}
fclose(f);
}
And here is the input:
8
q 0 addr2
q 0 addr1
q 0 addr1
q 1 addr4
q 1 addr1
q 1 addr2
f 4
q 1 addr4
Well expected output:
8
q 0 addr2
q 0 addr1
q 0 addr1
q 1 addr4
q 1 addr1
q 1 addr2
f 4
q 1 addr4
Actual output:
0 q 0 (null)
1 a 0
2 d 0
3 d 0
4 r 2
5 q 0 (null)
6 a 0
7 d 0
I have no idea what's going on

When you fscanf into q[i].addr, there has not yet any memory been allocated to q[i].addr. Now anything can happen because the string is placed in memory that is not yours.
You should also check the return value of fscanf to be suer the data was properly read.

Related

How to read a file, convert letters, and print string and integers to an array in c?

struct reviewStruct {
char reviewer[50];
int feedback[3];
};
int readReviews(FILE *file, struct reviewStruct reviews[10]) {
int i;
file = fopen("Names.txt", "r");
if(file == NULL) {
printf("Error");
exit(-1);
}
for(i = 0; i < 10; i++) {
fgets(reviews[i].reviewer, 50, file);
}
fclose(file);
for(i = 0; i < 10; i++) {
printf("%s", reviews[i].reviewer);
}
return 0;
}
Hello, I'm trying to read a file line by line and print it to an array, with a catch. Whenever a 'Y' or 'y' appears, it converts that letter into a 1, and if an 'N' or 'n' appears, it is converted into a 0 (zero), excluding the first word of every line. For example, I have a file with the following information:
charlie Y n N
priya N n Y
lance y y Y
stan N y n
arin N n N
This is the text file called Names.txt, I want to save the integer information to the array called "feedback", so that it looks like this when printed using a for loop:
1 0 0
0 0 1
1 1 1
0 1 0
0 0 0
How do I populate the feedback array such that it can be printed along with the names using a for loop as it is in the following image?
charlie 1 0 0
priya 0 0 1
lance 1 1 1
stan 0 1 0
arin 0 0 0
Thanks.

fscanf reading from file with while loop

i am very grateful about all you invloving in answer my question.
i found that this bug is caused by wrong operation of pointer. i have fixed it .
file to read:
L 0,1
L 1,1
L 2,1
L 3,1
S 4,1
L 5,1
S 6,1
L 7,1
S 8,1
L 9,1
S a,1
L b,1
S c,1
L d,1
S e,1
M f,1
each line startswith one whitespace end with '\n'.
i have write those code to read lines from file and calling helper(cacheSimulator) func :
function cacheSimulator is the starting point of open the file
cacheSimulator as follow
resStruct cacheSimulator(addrStruct* Arg, resStruct res){
resStruct *pRes = &res;
// fscanf vars
char op;
unsigned long addr;
int bytes;
int cacheSize = Arg->set * Arg->line * sizeof(unit);
unit *pCache = malloc(cacheSize);
if (!pCache) exit(1);
int block = 0, set = 0, tag = 0,
line = Arg->line; // this var save result in decimal.
int64_t maskCO, maskCI, maskCT; // address mask
maskOption optionCO = { Arg->block, 0},\
optionCI = { Arg->set, Arg->block },\
optionCT = { ADDRLEN - Arg->block - Arg->set,\
Arg->block + Arg->set };
int r = 0;
unsigned long time = 0;
unsigned long *ptime = &time;
char resChar[MAXRES] = {};
FILE* pFile = fopen(Arg->File,"r");
while (true) {
r = fscanf(pFile, " %c %lx,%d", &op, &addr, &bytes);
if (r!=3) break;
block = GetDecimalBit(addr, optionCO);
set = GetDecimalBit(addr, optionCI);
tag = GetDecimalBit(addr, optionCT);
memset(resChar, 0, sizeof(resChar));
if (op == 'M') {
LoadCache(tag, set, block, line, pCache, pRes, ptime, resChar);
strcat(resChar, " hit");
pRes->hits++;
} else if (op == 'L' || op == 'S') {
LoadCache(tag, set, block, line, pCache, pRes, ptime, resChar);
}
if (Arg->verbose) {
printf("%c %lx,%d %s\n", op, addr, bytes, resChar);
}
}
fclose(pFile);
free(pCache);
return res;
}
the function LoadCache access a 2D array and deal with a output parameter resChar.
LoadCache
void LoadCache(int tag,
int set,
int block,
int line,
unit* pCache,
resStruct* pRes,
unsigned long *time,
char ret[] ) {
int get = 0;
unit *pTarget = NULL;
while (!get) {
for (int l = 0; l < line; ++l) {
pTarget = pCache + (set*line+l)*sizeof(unit);
if (pTarget->valid && pTarget->tag == tag){
(pRes->hits)++;
pTarget->timer = *time;
get = 1;
strcpy(ret, "hit");
break;
} else if (!pTarget->valid) {
(pRes->misses)++;
pTarget->timer = *time;
pTarget->valid = 1;
pTarget->tag = tag;
get = 1;
strcpy(ret, "miss");
break;
}
}
if (!get) {
WriteCache(tag, set, block, line, pCache, pRes, time);
(pRes->misses)++;
strcpy(ret, "miss eviction");
get = 1;
}
}
++*time;
}
but i got this output:
L 0,1 miss
L 1,1 hit
L 2,1 miss eviction
L 3,1 hit
S 4,1 miss eviction
L 5,1 hit
S 6,1 miss eviction
L 7,1 hit
S 8,1 miss eviction
compared to the file what i fopen, it just read the first 9 lines.
i have gdb the excutable obj. i found that when execute the while loop to read the line 10, fscanf would return 1, but 3 what is expected.
the gdb output:
Breakpoint 2, cacheSimulator (Arg=0x7fffffffda80, res=...) at helper.c:88
88 r = fscanf(pFile, " %c %lx,%d", &op, &addr, &bytes);
1: r = 3
(gdb) c
Continuing.
L 7,1 hit
Breakpoint 2, cacheSimulator (Arg=0x7fffffffda80, res=...) at helper.c:88
88 r = fscanf(pFile, " %c %lx,%d", &op, &addr, &bytes);
1: r = 3
(gdb) c
Continuing.
S 8,1 miss eviction
Breakpoint 2, cacheSimulator (Arg=0x7fffffffda80, res=...) at helper.c:88
88 r = fscanf(pFile, " %c %lx,%d", &op, &addr, &bytes);
1: r = 3
(gdb) n
89 if (r!=3) break;
1: r = 1
as you can see, there is no problem reading the first 9 lines.
but return value from fscanf() is 1 when the 10th line is read.
tried executing the code, got segmentation fault. replaced "open($filepath,"r");" with "fopen($filepath,"r");" and after this code got executed successfully, and didn't with encounter any error aftr that.
#include <stdio.h>
char * filepath = "/Users/test/temp.txt";
int main () {
char op=0;
unsigned long addr=0;
int bytes=0;
FILE* pFile = fopen(filepath,"r");
if (!pFile) {
printf("Failed to open file\n");
return 0;
}
while (fscanf(pFile, " %c %lx,%d\n", &op, &addr, &bytes) == 3) {
printf(" %c , %lx %d\n", op, addr, bytes);
//op = 0;
//addr=0;
//bytes=0;
}
return 0;
}
output:
NISM-M-9168:dirtest nism$ cc fileread.c
NISM-M-9168:dirtest nism$ ./a.out
L , 0 1
L , 1 1
L , 2 1
L , 3 1
S , 4 1
L , 5 1
S , 6 1
L , 7 1
S , 8 1
L , 9 1
S , a 1
L , b 1
S , c 1
L , d 1
S , e 1
M , f 1

Build a binary tree using two arrays given in C

I have a question. How can I add two arrays L(elements of theleft subtree) and D(elements of the right subtree) and create a binary tree? It's not a binary search tree. However these data that i have are stored in a file in which i have managed to convert the lines with numbers into int arrays S->Left elements and D->Right elements. Finally with the p i have stored the number of nodes from the first line. The file contains these lines:
7 ->Number of nodes
2 4 0 0 7 0 0 ->Left subtree elements
3 5 6 0 0 0 0 ->Right subtree elements
However my assignment is to build this code and do a postorder,inorder and preorder traversal of the binary tree and the output should look like this:
Preorder: 1 2 4 5 7 3 6
Inorder: 4 2 7 5 1 3 6
Postorder: 4 7 5 2 6 3 1
It's not clear for me why 1 is there. I am sure that 1 is the root but i don't know how to add the rest of the elements to the binary tree from S and D arrays.
My code so far looks like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int p;
int length1, length2, *S, *D;
int j = 0, k;
const char *v1;
const char *v2;
FILE *fptr = fopen("sd.in", "r");
if (fptr == NULL)
{
printf("Failed to open file\n");
return - 1;
}
char buf[3][100];
int i = 0;
while ((fgets(buf[i], 100, fptr) != NULL) && (i < 3))
{
printf("%s\n", buf[i++]);
}
fclose(fptr);
p = atoi(buf[0]);
v1 = buf[1];
v2 = buf[2];
length1 = strlen(v1);
length2 = strlen(v2);
S = (int*)malloc(length1 *sizeof(int));
D = (int*)malloc(length2 *sizeof(int));
while (sscanf(v1, "%d%n", &S, &length1) == 1)
{
printf(" element %d is %d\n", j, S);
v1 += length1;
j++;
}
while (sscanf(v2, "%d%n", &D, &length2) == 1)
{
printf(" element %d is %d\n", k, D);
v2 += length2;
k++;
}
printf("%d\n", p);
return 0;
}

Storing subsets of a array

this program is "calculating" all subsets of the array source. I need to store the resulting values in another 2D filed named polje. If I just use the printf("%d %d %d ", source[i][0], source[i][1], source[i][2]); the code works fine but something fails when it is trying to copy everything into the resulting field. I suppose I am dogin something wrong in the indexing of the array polje.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
int f;
int i,j;
int source[2][3] = {{0,3,5},{3,4,2}};
int currentSubset = 3;
int polje[8][3];
for(i=0;i<8;i++){
for(j=0;j<3;j++){
polje[i][j]=0;
}}
int tmp;
while(currentSubset)
{
tmp = currentSubset;
for( i = 0; i<3; i++)
{
if (tmp & 1)
{
printf("%d %d %d ", source[i][0], source[i][1], source[i][2]); //writes out everything I want
polje[currentSubset][0]=source[i][0];
polje[currentSubset][1]=source[i][1];
polje[currentSubset][2]=source[i][2];
}
tmp >>= 1;
}
printf("\n");
currentSubset--;
}
for(i=0;i<8;i++){
for(j=0;j<3;j++){
printf("%d ", polje[i][j]);
}printf("\n");}
return (EXIT_SUCCESS);
}
The output field should be:
0 3 5
3 4 2
3 4 2
0 0 0
0 3 5
0 0 0
0 0 0
0 0 0
But instead it is:
0 3 5
3 4 2
3 4 2
0 0 0
*0 0 0*
0 0 0
0 0 0
0 0 0
tmp is a bit mask with only two bits, so the inner loop should be for ( i = 0; i < 2; i++ ).
Also the correct index into the polje array is polje[currentSubset * 2 + i][0] since each subset in polje takes two spaces and i is either 0 or 1.
I think you just have a logic error. Your loop's skeleton is:
currentSubset = 3;
while ( currentSubset )
{
// ...
polje[currentSubset][...] = ...;
// ...
currentSubset--;
}
So you never write to any rows except the first three.

Read integers from stdin and store in 2d array (C)

I'm trying to read a text file containing integers via stdin and store the values in a 9x9 array (please note that the file must be read via stdin and not as an arg)
This is what I have:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main()
{
int puzzle[9][9];
int i,j,count=0;
char value[81];
for( i = 0; i < 9; i++ ) {
for( j = 0; j < 9; j++ ) {
scanf("%c", &value[count]);
puzzle[i][j] = value[count] - '0';
count++;
}
}
}
But it doesn't seem to convert the ASCII characters from scanf to int, which is what I thought the value[count] - '0' was supposed to do, so I end up getting values like this:
-16-16-160-16-160-16-161
Basically i'm trying to do exactly whats described in this thread, but in C instead of C++:
How to convert a 2d char array to a 2d int array?
Edit -
The input file looks like this (contains both white space and new lines):
0 0 1 9 0 0 0 0 8
6 0 0 0 8 5 0 3 0
0 0 7 0 6 0 1 0 0
0 3 4 0 9 0 0 0 0
0 0 0 5 0 4 0 0 0
0 0 0 0 1 0 4 2 0
0 0 5 0 7 0 9 0 0
0 1 0 8 6 0 0 0 7
7 0 0 0 0 9 2 0 0
The problem is not with the conversion line puzzle[i][j] = value[count] - '0';. The problem lies with the following scanf() statement, scanf("%c", &value[count]);. The scanf is reading the first white space. Use scanf(" %c", &value[count]); to read the input.
%c does eactly what it should: it reads one character. D'oh, it's whitespace? That doesn't matter. This is why...
... you shouldn't use %c but %d for scanning integers;
...you shouldn't use scanf() at all for something simple like this.
What I'd do if I were you:
int matrix[9][9];
int i = 0;
char buf[0x100];
while (fgets(buf, sizeof(buf), stdin)) {
char *end;
char *p = strtok_r(buf, " ", &end);
while (p) {
matrix[i / 9][i % 9] = strtol(p, NULL, 10);
i++;
p = strtok_r(NULL, " ", &end);
}
}
Is there any reason this doesn't work? Scan them in as integers.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main()
{
int puzzle[9][9];
int i,j,count=0;
char value[81];
for( i = 0; i < 9; i++ ) {
for( j = 0; j < 9; j++ ) {
scanf("%d", &value[count]);
puzzle[i][j] = value[count];
printf("%d", puzzle[i][j]); //to verify it is stored correctly
count++;
}
}
}
EDIT: since you said it's coming from a file, i copy/pasted the sample file you gave into C:\file.txt, and the following code appears to work just dandy.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main()
{
FILE *fp;
int puzzle[9][9];
int i,j,count=0;
int value[81];
fp = fopen("C:\\file.txt", "r");
for( i = 0; i < 9; i++ ) {
for( j = 0; j < 9; j++ ) {
fscanf(fp, " %d", &value[count]);
puzzle[i][j] = value[count];
printf("element %d is %d\n",count, puzzle[i][j]);
count++;
}
}
}

Resources