fscanf reading from file with while loop - c
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
Related
Can't read integers from File one by one correctly
In my case I can print the 50 4digits random generated numbers into the file named rastgele.txt but then ı need to read them from file one by one and store them in the array named dosyaOkuma[] and print them to the screen. But when ım try to scan and print them ı get irrelevant numbers so ı cant read them correctly from file. I need some help about reading int numbers from file correctly. Here is my File format: 2862 3232 2869 2993 1303 3799 2257 2296 2105 3502 1318 3348 1851 3741 1468 1605 1994 1005 2211 1646 3056 3319 2273 1436 2621 1882 3856 2869 2026 2789 2055 1205 1263 1051 3059 3275 2876 1703 3674 1539 2381 2513 2415 3613 1066 3796 2710 2578 1294 3255 Here is my code: #include <stdlib.h> int main(){ FILE *file; int sayilar[50]; int dosyaOkuma[50]; int i,x,y; srand ( time(NULL) ); for (i = 0; i < 50; i++) { int num = (rand() % 2999) +1000; sayilar[i] = num; } file = fopen("rastgele.txt","w"); for(x=0;x<50;x++){ fprintf(file,"%d ",sayilar[x]); } printf("Olusuturulan rastgele sayilar rastgele.txt dosyasina yazdirildi..."); for(y=0;y<50;y++){ fscanf(file,"%d",&dosyaOkuma[y]); //where ı read file... printf("\n%d. sayi = %1d",y+1,dosyaOkuma[y]); //where ı print files to screen... } return 0; } And here is my program output: 1. sayi = 101 2. sayi = 0 3. sayi = -285212433 4. sayi = 32765 5. sayi = 0 6. sayi = 0 7. sayi = 0 8. sayi = 0 9. sayi = 0 10. sayi = 0 11. sayi = -1697181492 ...
Include stdio.h and time.h Add rewind after writing and before reading. #include <stdio.h> #include <stdlib.h> #include <time.h> int main ( void){ FILE *file = NULL; int sayilar[50] = { 0}; int dosyaOkuma[50] = { 0}; int i = 0, x = 0, y= 0; srand ( time(NULL) ); for (i = 0; i < 50; i++) { int num = (rand() % 2999) +1000; sayilar[i] = num; } if ( NULL != ( file = fopen("rastgele.txt","w+"))) { for ( x = 0; x < 50; x++) { fprintf ( file,"%d ",sayilar[x]); } printf ( "Olusuturulan rastgele sayilar rastgele.txt dosyasina yazdirildi..."); rewind ( file); for ( y = 0; y < 50; y++) { if ( 1 == fscanf(file,"%d",&dosyaOkuma[y])) { printf("\n%d. sayi = %1d",y+1,dosyaOkuma[y]); } } fclose ( file); } return 0; }
Reading random input from file
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.
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; }
C - crypt() - Code takes longer to execute with 5 loops or more than with 4 loops but using the same parameter/hash
I'm taking an edx course called CS50. Maybe some of you are familiar with it. One of the problems set asks you to implement an algorithm to crack a password that was hashed using des-based encryption and is up to 4 characters. So far, so good. I've done it. But I decided to improve it a little bit and make it possible to crack passwords that are up to 8 characters, which is the maximum for des-based encryption. And the problem is, when I add the possibility of the fifth character (or more), my code doesn't work anymore. Here are my codes This one is working: #define _XOPEN_SOURCE #include <stdio.h> #include <unistd.h> #include <string.h> /* Use this to compile clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow crack4.c -lcrypt -lm -o crack4 */ int main(int argc, char *argv[]) { if (argc != 2) //Checks if number of command-line arguments is valid { printf ("usage: ./crack + hash \n"); return 1; //Retuns 1 (error) } char *hash = argv[1]; //Gets hash passed as argument char salt[3]; //Gets the salt salt[0] = hash[0]; salt[1] = hash[1]; salt[2] = '\0'; //All possible characters used in a DES-based hashed password (taken from gnu library) const char *const seedchars = " ./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; char text[9] = "\0"; //Text that is gonna be tried with crypt() for (int d = 0; d <= 64 ; d++) //To check for passwords of up to 4 characters { printf("d %d \n", d); if(d > 0) { text[4] = '\0'; //Defining null-terminator at index 4 text[3] = seedchars[d]; //Iterates through the seedchars list at index 3 } for (int c = 0; c <= 64 ; c++) //To check for passwords of up to 3 characters { if(c > 0) { if (d == 0) { text[3] = '\0'; //Defining null-terminator at index 3 } text[2] = seedchars[c]; //Iterates through the seedchars list at index 2 } for (int b = 0; b <= 64 ; b++) //To check for passwords of up to 2 characters { if(b > 0) { if (c == 0 && d == 0) { text[2] = '\0'; //Defining null-terminator at index 2 } text[1] = seedchars[b]; //Iterates through the seedchars list at index 1 } for (int a = 0; a <= 64 ; a++) //To check for passwords of up to 1 character { if(b == 0 && c == 0 && d == 0) { text[1] = '\0'; //Defining null-terminator at index 1 } text[0] = seedchars[a]; //Iterates through the seedchars list at index 0 char *password = crypt(text, salt); //Hash var text and save it to var password if (strcmp(hash, password) == 0) //Compares the hash passed as argv with created above { printf("%s\n", text); //prints the text that led to said hash return 0; //Returns 0 (okay) } } } } } return 1; //Retuns 1 (error) } This one isn't working: #define _XOPEN_SOURCE #include <stdio.h> #include <unistd.h> #include <string.h> /* Use this to compile clang -ggdb3 -O0 -std=c11 -Wall -Werror -Wshadow crack.c -lcrypt -lm -o crack */ int main(int argc, char *argv[]) { if (argc != 2) //Checks if number of command-line arguments is valid { printf ("usage: ./crack + hash \n"); return 1; //Retuns 1 (error) } char *hash = argv[1]; //Gets hash passed as argument char salt[3]; //Gets the salt salt[0] = hash[0]; salt[1] = hash[1]; salt[2] = '\0'; //All possible characters used in a DES-based hashed password (taken from gnu library) const char *const seedchars = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; char text[9] = "\0"; //Text that is gonna be tried with crypt() for (int h = 0; h <= 64 ; h++) //To check for passwords of up to 8 characters { if(h > 0) { text[8] = '\0'; //Defining null-terminator at index 8 text[7] = seedchars[h]; //Iterates through the seedchars list at index 7 } for (int g = 0; g <= 64 ; g++) //To check for passwords of up to 7 characters { if(g > 0) { if (h == 0) { text[7] = '\0'; //Defining null-terminator at index 7 } text[6] = seedchars[g]; //Iterates through the seedchars list at index 6 } for (int f = 0; f <= 64 ; f++) //To check for passwords of up to 6 characters { if(f > 0) { if (g == 0 && h == 0) { text[6] = '\0'; //Defining null-terminator at index 6 } text[5] = seedchars[f]; //Iterates through the seedchars list at index 5 } for (int e = 0; e <= 64 ; e++) //To check for passwords of up to 5 characters { if(e > 0) { if (f == 0 && g == 0 && h == 0) { text[5] = '\0'; //Defining null-terminator at index 5 } text[4] = seedchars[e]; //Iterates through the seedchars list at index 4 for (int d = 0; d <= 64 ; d++) //To check for passwords of up to 4 characters { printf("d %d \n", d); if(d > 0) { if (e == 0 && f == 0 && g == 0 && h == 0) { text[4] = '\0'; //Defining null-terminator at index 4 } text[3] = seedchars[d]; //Iterates through the seedchars list at index 3 } for (int c = 0; c <= 64 ; c++) //To check for passwords of up to 3 characters { if(c > 0) { if (d == 0 && e == 0 && f == 0 && g == 0 && h == 0) { text[3] = '\0'; //Defining null-terminator at index 3 } text[2] = seedchars[c]; //Iterates through the seedchars list at index 2 } for (int b = 0; b <= 64 ; b++) //To check for passwords of up to 2 characters { if(b > 0) { if (c == 0 && d == 0 && e == 0 && f == 0 && g == 0 && h == 0) { text[2] = '\0'; //Defining null-terminator at index 2 } text[1] = seedchars[b]; //Iterates through the seedchars list at index 1 } for (int a = 0; a <= 64 ; a++) //To check for passwords of up to 1 character { if(b == 0 && c == 0 && d == 0 && e == 0 && f == 0 && g == 0 && h == 0) { text[1] = '\0'; //Defining null-terminator at index 1 } text[0] = seedchars[a]; //Iterates through the seedchars list at index 0 char *password = crypt(text, salt); //Hash var text and save it to var password if (strcmp(hash, password) == 0) //Compares the hash passed as argv with created above { printf("%s\n", text); //prints the text that led to said hash return 0; //Returns 0 (okay) } } } } } } } } } } return 1; //Retuns 1 (error) } I'm using the hash below in both codes but it doesn't work on the second code. hash - 50fkUxYHbnXGw text - rofl Can someone please help me understand why is it not working? Thanks. Edit: The second code just finished running and it actually is working but it's taking way longer to crack the password. Here's a screenshot: I'm not being able to post it as a image for some reason, so here's the link http://imgur.com/a/GVWar Edit 2: adding link to image and fixing title Edit 3: re-fixing title
In the first case, for 4 characters, you have 4 nested loops. Which "for" will execute up to 64 times. So your code may run 64 ^ 4 = 16 million times. In the second case, for 8 characters, you have 8 nested loops. That makes 64 ^ 8 = 281 trillion times. The time your computer takes to execute the algoritm is proportional to that amount of loops. It grows so fast because your algorithm is exponential on the number of characters. If you want to learn more, search for "algorithm asymptotic notation".
You can think of a - h as wheels of comprised of 65 characters, with indexes 0 through 64. The last character is a line terminator from the declared value. If you were to add a printf for the value of e: crack08 50fkUxYHbnXGw e 1 d 0 d 1 d 2 d 3 d 4 d 5 d 6 d 7 d 8 d 9 d 10 d 11 d 12 d 13 d 14 d 15 d 16 d 17 d 18 d 19 d 20 d 21 d 22 d 23 ... d 63 d 64 e 2 d 0 d 1 d 2 ... You'd see we'd skip over the first value of e because h - f are 0. Finding a 4 character match is then deferred until e = 64 (the 65th index the '\0' string terminator). That represents more than 65 times longer before finding a 4 character password. Getting rid of the extra passes involves reorganizing the 'wheel' of characters used, adding a '\0' character as the first character, using that as string terminator for the first pass and skipping over it for subsequent passes: #define _XOPEN_SOURCE #include <stdio.h> #include <unistd.h> #include <string.h> int main(int argc, char *argv[]) { if (argc != 2) { printf ("usage: ./crack hash\n"); return 1; //Retuns 1 (error) } char *hash = argv[1]; char salt[3]; salt[0] = hash[0]; salt[1] = hash[1]; salt[2] = '\0'; # define WHEEL_SIZE 65 // all possible password characters // plus null character for shorter strings char seedchars[WHEEL_SIZE] = "#./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; char text[9]; // Text that is gonna be tried with crypt() text[8] = '\0'; // for h > 0 seedchars[0] = '\0'; // test for short strings first int a_first = 0; int b_first = 0; int c_first = 0; int d_first = 0; int e_first = 0; int f_first = 0; int g_first = 0; for (int h = 0; h <= WHEEL_SIZE - 1 ; h++) { text[7] = seedchars[h]; for (int g = g_first ; g <= WHEEL_SIZE - 1; g++) { text[6] = seedchars[g]; for (int f = f_first; f <= WHEEL_SIZE -1; f++) { text[5] = seedchars[f]; for (int e = e_first; e <= WHEEL_SIZE - 1; e++) { printf("e %2d\n", e); text[4] = seedchars[e]; for (int d = d_first; d <= WHEEL_SIZE - 1; d++) { printf("d %2d\n", d); text[3] = seedchars[d]; for (int c = c_first; c <= WHEEL_SIZE - 1; c++) { if (c > 0) b_first = 1; text[2] = seedchars[c]; for (int b = b_first; b <= WHEEL_SIZE - 1; b++) { text[1] = seedchars[b]; for (int a = a_first; a <= WHEEL_SIZE - 1; a++) { text[0] = seedchars[a]; char *password = crypt(text, salt); if (strcmp(hash, password) == 0) { printf("%s\n", text); return 0; } } b_first = 1; } c_first = 1; } c_first = 1; } d_first = 1; } e_first = 1; } f_first = 1; } g_first = 1; } return 1; } And that gives us the answer in the minimum time: crack 50fkUxYHbnXGw e 0 d 0 d 1 d 2 d 3 d 4 d 5 d 6 d 7 d 8 d 9 d 10 d 11 d 12 d 13 d 14 d 15 d 16 d 17 d 18 d 19 d 20 d 21 d 22 d 23 d 24 d 25 d 26 d 27 d 28 d 29 d 30 d 31 d 32 d 33 d 34 d 35 d 36 d 37 d 38 d 39 d 40 d 41 d 42 d 43 d 44 d 45 d 46 d 47 d 48 d 49 d 50 rofl A much more satisfactory answer.
How to read a user input string and store it in an Array
Trying to read user input string from the key board and assign it to an Array. It still confusing. Also any Idea what char ch = 97 is in this program? Thanks. #include<stdlib.h> int main() { int i = 0; int j = 0; int count[26]={0}; char ch = 97; char string[100]="readmenow"; for (i = 0; i < 100; i++) { for(j=0;j<26;j++) { if (tolower(string[i]) == (ch+j)) { count[j]++; } } } for(j=0;j<26;j++) { printf("\n%c -> %d",97+j,count[j]); } }
to read user input do this: #include <stdio.h> // for fgets #include <string.h> // for strlen fgets(string,sizeof(string),stdin); string[strlen(string)-1] = '\0'; // this removes the \n and replaces it with \0 make sure you include proper headers Also ch= 97; is same as doing ch = 'a'; EDIT: scanf is great for reading input as a string as long as the string doesn't have space. fgets is much better EDIT 2 #include <stdio.h> #include <stdlib.h> #include <string.h> int main(){ int i=0,j=0; char input[50]; // make the size bigger if you expect a bigger input printf("Enter string = "); fgets(input,sizeof(input),stdin); input[strlen(input)-1] = '\0'; int count[26]={0}; for (i = 0; i < strlen(input); i++) { for(j=0;j<26;j++) { if (tolower(input[i]) == ('a'+j)) { count[j]++; } } } for(j=0;j<26;j++) { printf("\n%c -> %d",'a'+j,count[j]); } return 0; } Output: $ ./test Enter string = this is a test string a -> 1 b -> 0 c -> 0 d -> 0 e -> 1 f -> 0 g -> 1 h -> 1 i -> 3 j -> 0 k -> 0 l -> 0 m -> 0 n -> 1 o -> 0 p -> 0 q -> 0 r -> 1 s -> 4 t -> 4 u -> 0 v -> 0 w -> 0 x -> 0 y -> 0 z -> 0
char ch= 97 it means ch='a' it use ASCII (American Standard Code for Information Interchange)