I am trying to run my code on eclipse with ubuntu.
I have dumped the data using fprintf into one txt file and reading that file by using fscanf. I am not able to read that values into data array.
Below is my code :
#include <stdio.h> /* printf, scanf, NULL */
#include <stdlib.h> /* malloc, free, rand */
int main(){
char* data;
FILE *fp;
size_t result;
data = (char*) malloc (sizeof(char)*(1280*800));//Size of one frame
if (data==NULL){
printf("NOt able to allocate memory properly\n");
exit (1);
}
fp = fopen ("\\home\\studinstru\\Desktop\\filedump.txt", "r");
if(fp==NULL){
printf("Error in creating dump file\n");
exit (1);
}
for(int m = 0;m<1280;m++){
for(int n = 0;n<800;n++){
fscanf(fp,"%d/t",data[m*800 + n]);
}
}
fclose(fp);
return 0;
}
This is my filedump.txt data :
79 78 78 77 78 79 81 95
82 81 81 81 82 82 82 82
79 78 78 77 78 79 81 95
82 81 81 81 82 82 82 82
79 78 78 77 78 79 81 95
82 81 81 81 82 82 82 82 ....
Can you tell what is wrong in this?
Your code has a couble of problems
Your fscanf() format is wrong and you are passing the value instead of it's address, you should use
fscanf(fp, "%d", &data[n + 800 * m]);
if you meant "\t" whcih is the tab character, it's not needed anyway and passing the value instead of it's address is Undefined Behavior, because fscanf() will treat the value as a pointer, and it's not likely pointing to a valid memory address, moreover, it's unintialized which is another reason for undefined behavior.
You declared data as char *data and store int's in it, that is also Undefined Behavior.
You must check the return value of fscanf() beacuse if it fails, then the value will be uninitialized and there will be once again, Undefined Behavior and also you are going to read past the end of the file because you will never know if you reached it.
You are writing into the file and you open it for reading, this
fprintf(fp, "\n");
is wrong, you don't need it to read from the file.
Don't cast the result of malloc() though this is not causing problems in this case, it will improve the quality of your code.
Don't use sizeof(char) it makes your code harder to read and it's completely unnecessary since the standard mandates that sizeof(char) == 1.
You don't need the nested loop to read the data, because the shape of the data is irrelevant since fscanf() ignores all whitespace characters.
It is sufficient to read throug the file and use a counter to move through the array, at the end you can check how many values where read to verify the integrity of the data.
This is a fixed version of your code
#include <stdio.h> /* printf, scanf, NULL */
#include <stdlib.h> /* malloc, free, rand */
int main()
{
FILE *fp;
size_t index;
int *data;
data = malloc(1280 * 800);
if (data == NULL)
{
printf("NOt able to allocate memory properly\n");
return 1;
}
fp = fopen("\\home\\studinstru\\Desktop\\filedump.txt", "r");
if (fp == NULL)
{
printf("Error in creating dump file\n");
free(data);
return 2;
}
while (fscanf(fp, "%d", &data[index]) == 1)
{
fprintf(stdout, "%d ", data[index]);
index += 1;
if (index % 800 == 0)
printf("\n");
}
fclose(fp);
return 0;
}
Note: I recommend the use of compiler warnings, they would help prevent silly mistakes and some other mistakes like char *data and reading int's into it.
Also, from your file path "\\home\\studinstru\\Desktop\\filedump.txt" it seems you are on a non-windows system, and very likely the directory separator is / instead of \, so the correct path has to be
"/home/studinstru/Desktop/filedump.txt"
Replace
fscanf(fp,"%d/t",data[m*800 + n]);
with
fscanf(fp,"%d/t",&data[m*800 + n]);
fscanf() needs address of destination variable as argument and not the variable itself.
Also I am not getting why are doing this:
fprintf(fp,"\n");
Related
I'm working a program for a class and it's proving much more difficult than I thought.
It's my very first experience with C, but I've had some experience with Java so I understand the general concepts.
My goal: read in a text file that has some formatting requirements contained within the file, store the file in an array, apply the formatting and output the formatted text to stdout.
The problem: reading in the file is easy, but I'm having trouble with the formatting and output.
The challenge:
--the input file will begin with ?width X, ?mrgn Y, or both (where X and Y are integers). these will always appear at the beginning of the file, and will each be on a separate line.
--the output must have the text formatted as per the formatting request (width, margin).
--additionally, there is a 3rd format command, ?fmt on/off, which can appear multiple times at any point throughout the text and will turn formatting on/off.
--just a few catches: if no ?width command appears, formatting is considered off and any ?margin commands are ignored.
--if a ?width command appears, formatting is considered on.
--the files can contain whitespace (as both tabs and spaces) which must be eliminated, but only when formatting is on.
--dynamic memory allocation is not allowed.
Easy for a first C program right? My professor is such a sweety.
I've been working on this code for hours (yes, I know it doesn't look like it) and I'm making little progress so if you feel like a challenge I would very much appreciate help of any kind. Thanks!
So far my code reads in the text file and formats the margin correctly. Can't seem to find a good way to eliminate whitespace (I believe tokenizing is the way to go) or do the word wrap when the length of the line is longer than the ?width command.
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #define MAX_LINE_LEN 133 /* max 132 char per line plus one extra for the new line char
6 #define MAX_LINES 300 /* max 300 lines per input file */
7 #define MAX_CHARS 39900 /* max number of characters in the file */
8
9 /* Initializes array used to store lines read in from text
10 file as well as output array */
11 char input[MAX_LINE_LEN];
12 char buffer[MAX_CHARS];
13 char word_wrap[MAX_LINE_LEN];
14
15 /* Functions */
16 void parameters(char [], FILE *);
17
18 /* Variables */
19 int width = 0;
20 int margin = 0;
21
22 /*
23 argc is the count of input arguments
24 *argv is a pointer to the input arguments
25 */
26 int main (int argc, char *argv[])
27 {
28 /* Creates file pointer */
29 FILE *fp = fopen(argv[1], "r"); /* r for read */
30
31 if (!fp) /* Error checking */
32 {
33 printf("Error: Could not open file");
34 return 0;
35 }
36
37 /* Retrieves width and margin parameters from input file */
38 parameters(input, fp);
39
40 fclose(fp); /* Closes file stream */
41
42 return 0;
43 }
44
45 void parameters(char input[], FILE *fp)
46 {
47 /* Gets input file text line by line */
48 while (fgets (input, 133, fp) != NULL)
49 {
50 /* Creates a pointer to traverse array */
51 char *p = input;
52
53 /* Checks for width parameter read in from text file */
54 if (input[0] == '?' && input [1] == 'w')
55 {
56 strtok(input, " "); /* Eliminates first token '?width' */
57 width = atoi(strtok(NULL, " ")); /* Stores int value of ASCII token
58 p = NULL;
59 }
60
61 /* Checks for margin parameter read in from text file */
62 if (input[0] == '?' && input[1] == 'm')
63 {
64 strtok(input, " "); /* Eliminates first token '?mrgn' */
65 margin = atoi(strtok(NULL, " ")); /* Stores int value of ASCII token
66 p = NULL;
67 }
68
69 if (p != NULL) /* skips printing format tokens at beginning of file */
70 {
71 if (width == 0) /* no width command, formatting is off by default */
72 {
73 printf("%s", p); /* Prints unformatted line of text */
74 }
75 else /* formatting is on */
76 {
77 printf("%*s" "%s", margin, " ", p); /* Prints formatted line of text
78 }
79 }
80 }
81 }
82
And here's an example input file, along with its proper output:
?width 30
?mrgn 5
While there are enough characters here to
fill
at least one line, there is
plenty
of
white space which will cause
a bit of confusion to the reader, yet
the ?fmt off command means that
the original formatting of
the lines
must be preserved. In essence, the
command ?pgwdth is ignored.
Output:
While there are enough
characters here to fill
at least one line, there
is plenty of white space
which will cause a bit of
confusion to the reader,
yet the ?fmt off command means that
the original formatting of
the lines
must be preserved. In essence, the
command ?pgwdth is ignored.
I have this code to read a file using mmap and print it using printf. The file has 10 lines, and contains nos 0-9 on each line.
My questions are:
1. Why my code doesn't terminate on EOF ? i.e. why doesn't it stop at while (data[i]!=EOF) ?
2. When I run it with while (data[i]!=EOF), the program always terminates at data[10567] ? where as the page size is 4096 bytes. Does 10567 bytes have any significance ?
Edit: I am not looking for alternative like using fscanf, fgets.
Thanks!
Code:
10 int main(int argc, char *argv[])
11 {
12 FILE *ifp, *ofp;
13 int pagesize, fd, i=0;
14 char *data;
15 struct stat sbuf;
16
18 if ((ifp = fopen("/home/t/workspace/lin", "r"))==NULL)
19 {
20 fprintf(stderr, "Can't open input file\n");
21 exit(1);
22 }
28 fd = fileno(ifp);
29 if (stat("/home/t/workspace/lin", &sbuf) == -1)
30 {
31 perror("stat");
32 exit(1);
33 }
34 pagesize = getpagesize();
35 printf("page size: %d\n", pagesize);
36 printf("file size: %d\n", sbuf.st_size);
37 if((data = mmap((caddr_t)0, sbuf.st_size, PROT_READ, MAP_SHARED, fd, 0)) == (caddr_t)(-1))
38 {
39 perror("mmap");
40 exit(1);
41 }
43 //while (data[i]!=EOF)
44 while (i<=sbuf.st_size)
45 {
46 printf("data[%d]=%c\n", i, data[i]);
47 i++;
48 }
50 return 0;
51 }
Output:
page size: 4096
file size: 21
data[0]=0
data[1]=
data[2]=1
data[3]=
data[4]=2
data[5]=
data[6]=3
data[7]=
data[8]=4
data[9]=
. . . .
data[18]=9
data[19]=
data[20]=
data[21]= // truncated my output here,
// it goes till data[10567] if I use `while (data[i]!=EOF)`
EOF is not stored in files. So there's no point comparing a byte from the file with EOF. If you use mmap, as opposed to getchar or equivalent, then you need to stat the file to find out how big it is.
Note that getc, fgetc and getchar return an int. Quoting the manpage (or the Posix standard), these functions return the next byte "as an unsigned char cast to an int, or EOF on end of file or error." The value of EOF must be such that it cannot be confused with "an unsigned char cast to an int"; typically, it is -1. It is possible for a random (signed) char to be equal to -1, so your test data[i]!=EOF may eventually turn out to be true as you scan through uninitialized memory, if you don't segfault before you hit the random byte.
In Unix, text files are not necessarily terminated with NULs either. In short, you should only try to reference bytes you know to be inside the file, based on the file's size.
You output looks correct. The only bug I see is that:
while (i<=sbuf.st_size)
should have <.
There is no EOF, such as a Control-Z, stored in the actual data. All standard functions such as getc will return EOF when their internal counter equivalent to your i is past but their own sbuf.st_size. That is to say, EOF is a fictitious character generated by getc and/or the OS.
The confusion perhaps arises because, if I recall correctly, MS-DOS text files actually contain a ^Z, and if you inadvertently fopen one in binary mode, you can see this unwanted ^Z. Unix does not have this distinction.
With respect to your question:
Does 10567 bytes have any significance ?
I would say no. My guess is that data[10567] happens to be the first byte of memory equal to 0xFF, which is promoted to -l (assuming your char is signed), which matches EOF.
Today, I read a blog named by "a bug of fread?", I didn't find any reason for it, so I paste it here waiting for any genius.
First, the purpose of the program is to read a file(readme.txt) and print the content, and I test it with Visual Studio 2010.
The content of the readme is :
1234;
abcd;
ABCD;
The hex value of readme is :
31 32 33 34 3b 0d 0a 61 62 63 64 3b 0d 0a 41 42 43 44 3b
Here is the code:
#include <stdio.h>
#include <string.h>
#define BUF_SIZE 1024
int main()
{
FILE *fp = NULL;
int rcnt = 0;
char rbuf[BUF_SIZE];
fp = fopen("readme.txt", "r");
if (NULL == fp)
{
printf("fopen error.\n");
return -1;
}
printf("--------------------------\n");
memset(rbuf, 0, BUF_SIZE);
fseek(fp, 0, SEEK_SET);
rcnt = fread(rbuf, 1, BUF_SIZE, fp);
printf("read cnt = %d\n", rcnt);
printf("%s\n", rbuf);
return 0;
}
Such a simple code, and the expected result is :
--------------------------
read cnt = 17
1234;
abcd;
ABCD;
Total 17 count include 15 characters and 2 '\n'.
But I got the below result:
--------------------------
read cnt = 17
1234;
abcd;
ABCD;D;
PS: If call fopen function with "rb", or if define the macro BUF_SIZE smaller, I got the correct result.
fread() doesn't return a NUL terminated string, but printf("%s") ask for a NUL terminated string.
You have to add a '\0' at the end of the read buffer: rbuf[rcnt] = '\0'.
And remember to read one byte less than the buffer size to leave room for the NUL byte.
I think it's wrong to use fread(), a binary reading API, with a text file. The default mode (if you just say "r") is text.
Note that FILE * I/O in text mode typically does line-termination translation, so that you can pretend that lines end with \n when they might in fact physically end with \r\n (as yours do).
This conversion might introduce confusion somewhere; which is why switching to binary mode makes it work again as no such translation happens in binary mode.
16 char* input = (char*) argv[1];
17 FILE *fp = fopen (input, "r");
18 if( fp == NULL)
19 {
20 printf(" reading input file failed");
21 return 0;
22 }
23 fseek(fp,0,SEEK_END);
24 int file_size = ftell(fp);
29 rewind(fp);
30 int i;
31 int totalRun;
32 char * temp;
33 char* model;
34 char* example;
36 fscanf(fp,"%d",&totalRun);
37 fscanf(fp,"%s",model);
Above is my code I get this error at line 37 "fscanf(fp,"%s".model)"
Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: KERN_PROTECTION_FAILURE at address: 0x00007fff5fc00730 0x00007fff8db20bcb in __svfscanf_l ()
What can cause this ?? I looked into *fp in gdb. before reading totalRun _offset = 0 and after reading _offset = 4096. content of totalRun was correct ("3"). I only read one line and why is offset 4096? Also what is _blksize referring to in FILE.
Thank you
You need to allocate memory for model, it is an uninitialised pointer. Also ensure fscanf() does not read beyond the array assigned to model. If model does not need to by dynamically allocated then just use a local array. For example:
char model[1024];
if (1 == fscanf(fp, "%1023s", model))
{
}
Always check the return value of fscanf(), which returns the number of successful assignments, otherwise the program will be processing uninitialised variables if the call to fscanf() fails.
The variable model is not initalized. You must allocated memory for it before it can be used in the fscanf() method. You can do in two ways:
Statically - char model[1024];
Dynamically - char * model = (char*) malloc(1024); Don't forget to use free() to deallocate the buffer once you are done.
I cannot understand why a call to read after an lseek returns 0 number of bytes read.
//A function to find the next note for a given userID;
//returns -1 if at the end of file is reached;
//otherwise, it returns the length of the found note.
int find_user_note(int fd, int user_uid) {
int note_uid = -1;
unsigned char byte;
int length;
while(note_uid != user_uid) { // Loop until a note for user_uid is found.
if(read(fd, ¬e_uid, 4) != 4) // Read the uid data.
return -1; // If 4 bytes aren't read, return end of file code.
if(read(fd, &byte, 1) != 1) // Read the newline separator.
return -1;
byte = length = 0;
while(byte != '\n') { // Figure out how many bytes to the end of line.
if(read(fd, &byte, 1) != 1) // Read a single byte.
return -1; // If byte isn't read, return end of file code.
//printf("%x ", byte);
length++;
}
}
long cur_position = lseek(fd, length * -1, SEEK_CUR ); // Rewind file reading by length bytes.
printf("cur_position: %i\n", cur_position);
// this is debug
byte = 0;
int num_byte = read(fd, &byte, 1);
printf("[DEBUG] found a %d byte note for user id %d\n", length, note_uid);
return length;
}
The variable length value is 34 when it exist the outer while loop and the above code produces cur_position 5 (so there are definitely at least 34 bytes after the lseek function returns), but the variable num_byte returned from function read always returns 0 even though there are still more bytes to read.
Does anyone know the reason num_byte always return 0? If it is a mistake in my code, am not seeing what it is.
Just for information, the above code was run on the following machine
$ uname -srvpio
Linux 3.2.0-24-generic #39-Ubuntu SMP Mon May 21 16:52:17 UTC 2012 x86_64 x86_64 GNU/Linux
Update:
I upload the full code here
This is the content of file that I try to read
$ sudo hexdump -C /var/notes
00000000 e8 03 00 00 0a 74 68 69 73 20 69 73 20 61 20 74 |.....this is a t|
00000010 65 73 74 20 6f 66 20 6d 75 6c 74 69 75 73 65 72 |est of multiuser|
00000020 20 6e 6f 74 65 73 0a | notes.|
00000027
$
If length is an unsigned type smaller than off_t (for instance, size_t on a 32-bit machine), then length*-1 is going to be a huge value (somewhere around 4GB perhaps). This could be the problem. Storing the result of lseek into a long (again, if it's 32-bit) will apply an implementation-defined conversion, probably truncation, that leaves you with a small value again.
I see that your machine is 64-bit, but perhaps you're running a 32-bit userspace?
In any case, why not run your program under strace to see what system calls it's making? That will almost surely clear the issue up quickly.
I finally found the issue!!! I have to put #include <unistd.h> in order to use the correct lseek(). However I'm not sure why without including unistd.h it was compile-able though resulting in unexpected behavior. I thought that without including the prototype of a function, it shouldn't even compile-able.
The code was written in Hacking: The Art of Exploitation 2nd Edition by Jon Erickson and I have verified that in the book, there is no #include <unistd.h>.
With the initial variable length set to 34, the above code would
produce cur_position 5 (so there are definitely at least 34 bytes
after the lseek function returns)
This not necessarily is the case, as one could seek around beyond the end of file without getting any errors.
See the excerpt from lseek()'s man page below:
The lseek() function allows the file offset to be set beyond the
end of the file (but this does not change the size of the file).
So one could very well receive a value form lseek()ing, which still points beyond the end of the file. So read()ing from this position will still return 0 (as is's beyond end-of-file).
Also I agree with R.., that taking more care in using the correct types (the types used by the methods used) isn't a bad idea.
Update: also you might take care to include all headers for system functions you call. To check for such I strongly recommand to use gccs option -Wall to switch on all compiler warnings, they are for free ... ;-)