I'm trying to construct a string - for every 80 chars in the loop, to add 7 tabs to the beginning of the line, and a new line at the end.
It should print out 7 tabs, then 80 chars, then 1 new line and so on.
However, something strange is happening. It's printing a new line straight after the first 2 chars and then everything is skewed from then on.
I'm also not sure why I need % 40 rather than % 80 - is it because there are 2 bytes?
I think generally im getting confused by 2 bytes.
void do_file(FILE *in, FILE *out, OPTIONS *options)
{
char ch;
int loop = 0;
int sz1,sz2,sz3;
int seeker = offsetof(struct myStruct, contents.datas);
//find total length of file
fseek(in, 0L, SEEK_END);
sz1 = ftell(in);
//find length from beggining to struct beginning and minus that from total length
fseek(in, seeker, SEEK_SET);
sz2 = sz1 - ftell(in);
int tabs = (sz2 / 80) * 8;// Total size / size of chunk * 8 - 7 tabs and 1 new line char
sz3 = ((sz2 + 1 + tabs) * 2); //Total size + nuls + tabs * 2 for 2 bytes
char buffer[sz3];
char *p = buffer;
buffer[0] = '\0';
while (loop < sz2)
{
if(loop % 40 == 0){
//Add 7 tabs to the beginning of each new line
p += sprintf(p, "%s", "\t\t\t\t\t\t\t");
}
fread(&ch, 1, 1, in);
//print hex char
p += sprintf(p, "%02X", (ch & 0x00FF));
if(loop % 40 == 0){
//Add a new line every 80 chars
p += sprintf(p, "%s", "\n");
}
strcat(buffer, p);
loop++;
}
printf("%s", buffer);
}
However, something strange is happening. It's printing a new line straight after the first 2 chars and then everything is skewed from then on.
It's because of the initial value of loop, try with int loop = 1;
I'm also not sure why I need % 40 rather than % 80 - is it because there are 2 bytes?
I think generally im getting confused by 2 bytes.
The point is, for each character you read in input file, you write two characters in buffer, because you decided to print characters as two bytes (%02X).
Now what is your need:
insert LF and tabs each 80 characters of the input file? (Is that your expecting?)
insert LF and tabs each 80 characters of the output? (That is what you coded)
Related
I have the following text file
0 0 0 debut
1 120 0 permis exploitation
2 180 1 1 piste 6km
3 3 1 2 installation sondeuses
4 30 1 2 batiments provisoires
5 60 1 2 groudronnage piste
6 90 1 4 adduction eau
7 240 2 3 4 campagne sondage
8 180 3 5 6 7 forage 3 puits
9 240 3 5 6 7 construction bureaux logements
10 30 2 8 9 transport installation matériel
11 360 2 8 9 traçage du fond
12 240 2 8 9 construction laverie
13 0 3 10 11 12 fin des travaux
Each line is the representation of a task and is described as followed: the first number is and ID, the second is the duration, the third is the number of previous tasks that are required, and all the numbers afterward are the IDs of the required tasks. Finaly the string in the end is the title of the string.
I'm trying to fill an array of those struct by reading this file. Here is the struct:
typedef struct{
int id;
int duration;
int nbPrev; /* number of required previous tasks */
int prev[NMAXPREV]; /*array of required previous tasks*/
char title[LGMAX];
}Task ;
Here is my code to read the file
int readTasksFile(char* file_name, Task t[])
{
FILE* f;
char line[256] = {'\0'};
int i = 0;
char c[1] = {0};
if((f = fopen(file_name, "r")) == NULL)
{
perror("The file couldn't be opened");
exit(EXIT_FAILURE);
}
while (fgets(line, 256, f) != EOF)
{
sscanf_s(line, "&d &d &d", &(t[i].id), &(t[i].duration), &(t[i].nbPrev));
i++;
}
fclose(f);
return 0;
}
How can I read all the previous tasks number in a line considering it is variable and still be able to read the title afterward ?
How can I read all the previous tasks number in a line considering it is variable and still be able to read the title afterward ?
The 3rd int should be the number of following ints.
Use "%n" to record scan offset.
After reading the .prev[], copy the rest of the line to .title.
Add error checking. This is very important, especially for complex input.
// Untested code to get OP started
// while (fgets(line, 256, f) != EOF) Comparing against EOF is incorrect
while (fgets(line, sizeof line, f)) {
int offset = 0;
// Use %d, not &d
if (sscanf(line, "%d %d %d %n",
&t[i].id, &t[i].duration, &t[i].nbPrev, &offset) != 3) {
// Handle bad input, for now, exit loop
break;
}
if (t[i].nbPrev < 0 || t[i].nbPrev > NMAXPREV) {
// Handle bad input, for now, exit loop
break;
}
char *p = line + offset;
int prev;
// Populate t[i].prev[]
for (prev = 0; prev < t[i].nbPrev; prev++) {
if (sscanf(p, "%d %n", &t[i].prev[prev], &offset) != 1) {
break;
}
p += offset;
}
if (prev != t[i].nbPrev) {
// Handle bad input, for now, exit loop
break;
}
// remaining text
int len = strlen(p);
if (len > 0 && p[len-1] == '\n') p[--len] = '\0'; // consume potential trailing \n
if (len >= LGMAX) {
// Handle bad input, for now, exit loop
break;
}
strcpy(t[i].title, p);
i++;
}
return i; // Let caller know of successful lines parsed.
Advanced: robust code would use strtol() instead of "%d" and sscanf().
readTasksFile() should also pass in the max number of Task t[] that can be read.
You could also scan by line and assign the two first numbers to id and duration, then do an int analysis and add the rest of the elements to nbPrev until you encounter a letter.
I don't know if this would be the best way to do it, but it's how I would do it.
Why don't you create also a list each time you register in struct nbPrev?
Like, instead of nbPrev being of type int, make it of type list?
I'd like to send a message over a socket that looks like so: "USER anonymous\r\n".
In order to create a formatted string instead of a constant string, I used snprintf(). Unfortunately, it does not seem to copy the newline character \n, but just the carriage return \r.
#define USERNAME_ANONYMOUS "anonymous"
[...]
// Inside a function.
int sz = snprintf(NULL, 0, "USER %s\r\n", USERNAME_ANONYMOUS);
char* username = NULL;
if ((username = calloc(sz + 1, sizeof(char))) == NULL) {
perror("Could not allocate memory");
return;
}
snprintf(username, sz, "USER %s\r\n", USERNAME_ANONYMOUS);
for (int i = 0; i <= sz; i++) {
printf("%c %d\n", username[i], username[i]);
}
The output:
U 85
S 83
E 69
R 82
32
a 97
n 110
o 111
n 110
y 121
m 109
o 111
u 117
s 115
13
0
0
From this snprintf (and family) reference:
At most bufsz - 1 characters are written.
The size you provide must be including the terminator. You need to use sz + 1 to print the full string.
Well, if you allocate a buffer of size sz + 1 then pass that buffer size to the second snprintf call, which is sz + 1 and not sz, which is the number you pass.
The second call to snprintf should read:
snprintf(username, sz + 1, "USER %s\r\n", USERNAME_ANONYMOUS);
or it will overwrite the last \n with the null terminator, because it has not enough space for the whole string you want to print.
samplegame.txt(actual_file)
6
2 3 3
11 2
18 1
10 3
22 14
30 19
8 16
12 24
20 33
i want to read data .txt file into my C program.for each line separate them and store them in the variable,so i can use in further step.i'm trying to use
FILE* file = fopen (argv[1], "r");
int i = 0;
fscanf (file, "%d", &i);
while (!feof (file))
{
//printf ("%d ", i);
fscanf (file, "%d", &i);
}
fclose (file);
but i got all the number in one line and can't figure out how to separate each group like
int board_size = 6 << 1st line
int minion_box_size = 2; << 2nd line
int trap_size = 3;
int trampoline_size = 3;
int minion_box[minion_box_size] = {11,18}; << 3rd to N line
int minion_walk[minion_box_size] = {2,1};
int trap_position[trap_size] = {10,22,30}; << N+1 to M line
int trap_end[minion_box_size] = {3,14,19};
int trampoline_position[trampoline_size] = {8,12,20}; << M+1 to k line
int trampoline_jump[trampoline_size] = {16,24,33};
Anyone has a suggestion ?
samplegame.txt(explained)
______Board_________
6 // size of game board
_____size of each item_________
2 3 3 // first number in this line is Minion_box,which means there is 2 Minion_box
// Second number is trap_holes,which means there is 3 traps
// third number is trampoline,which means there is 3 trampolines
_____Minion_Box_______
// first number : where the minion_box are
// Second number : how many step that the minion can walk
11 2 // the box is in 11th block , minion has aiblity to walk 2 step
18 1 // the box is in 18th block , minion has ability to walk 1 step
______Traps__________
// first number : where the traps are
// Second number : the block you gonna be,after stepping on the trap.
10 3 // there is a trap hole in the 10th block,step on it and you will fall down 3rd block
22 14 // a trap hole in the 22th block,fall down to 14th block
30 19 // a trap hole in the 30th block,fall down to 19th block
____trampoline_______
// first number : where the trampoline are
// Second number : the block you gonna be,after stepping on the trampoline.
8 16 // there is a trampoline in 8th block,if you step on it you will jump to 16th block
12 24 // trampoline in 12th block,jump to 24th block
20 33 // trampoline in 20th block,jump to 33th block
Sorry for bad english and really long post,since i'm not good in english so i'm trying to show the example as much as possible :(
If you want to read a file line after line, better use fgets() and sscanf().
char buffer[BUFFER_SIZE]; // with a #define BUFFER_SIZE 1024 or whatever sooner in the code
int first_value, second_value;
if (fgets(buffer, BUFFER_SIZE, f) == NULL)
{
if ferror(f)
{
perror("");
}
exit(1);
}
if (sscanf(buffer, "%d %d", &first_value, &second_value) != 2)
{
fprintf(stderr, "missing value\n");
exit(1);
}
I have a program that reads from STDIO_FILENO. The input source is a txt file which contains 15 integers. After calling read and storing the returned value in n. I inspect it with gdb print n. Gdb tells me that read returned 45 bytes. I was expecting 60 bytes based on (32bit x 15) / 8. Can someone explain to me where I'm making the bad calculation.
#define BUFFSIZE 4096
int main(int argc, char * argv[])
{
int n;
char buf[BUFFSIZE];
while((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0)
if(write(STDOUT_FILENO, buf, n) != n)
err_sys("write error");
if(n < 0)
err_sys("read error");
exit(0);
}
Breakpoint 1, main (argc=1, argv=0x7fff5fbffb38) at stdin_stdout.c:10
10 while((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0)
(gdb) print n
$1 = 0
(gdb) n
Breakpoint 2, main (argc=1, argv=0x7fff5fbffb38) at stdin_stdout.c:11
11 if(write(STDOUT_FILENO, buf, n) != n)
(gdb) print n
$2 = 45
You are confusing numbers with representations of numbers. Since this is a text file, it contains text, not integers.
You can, for example, convert the text "12 32" into the integer twelve and the integer thirty-two, but you have to do it. You have to use base 10 and you have to agree that a space separates integers. The text will be five bytes if each character is one byte. You can then convert it into 8 bytes (two 32-bit integers) if you want. But that conversion has to actually be done, it doesn't do itself.
I'm trying to build a float number from a binary file with the following format:
first 4 bytes represents the number of digits on the left side of "."
We'll call that X
Next 4 bytes represents the number of digits on the right side of "."
We'll call that Y
Next byte represents the number's sign : "1" => '-', "0" => "+"
Next X+Y bytes represents the number's digits.
Example:
Data.bin:
4 2 0 2 8 3 9 5 3
The number should be : 2839.53
I've the structure :
typedef struct {
unsigned int digitsBefore;
unsigned int digitsAfter;
char sign;
char *digits;
} Number;
Function used to parse and fill the structure :
Number *fromBinaryToNumber(FILE *file){
int counter = 0, size = 0, i = 0;
size_t bytes_read;
unsigned int firstIndex, secondIndex;
char sign;
char *digits;
Number *nr = calloc(1, sizeof(Number));
// reading digits before
bytes_read = fread(&firstIndex, sizeof(unsigned int), 1, file);
nr->digitsBefore = firstIndex;
printf("Bytes read : %zu\n", bytes_read);
printf("First index %d\n", firstIndex);
size += firstIndex;
// reading digits after
bytes_read = fread(&secondIndex, sizeof(unsigned int), 1, file);
nr->digitsAfter = secondIndex;
printf("Bytes read : %zu\n", bytes_read);
printf("Second index %d\n", secondIndex);
size += secondIndex;
// reading sign
bytes_read = fread(&sign, sizeof(char), 1, file);
nr->sign = sign;
printf("Bytes read : %zu\n", bytes_read);
printf("Sign : %.2X\n", sign);
//reading digits
digits = calloc(size, sizeof(unsigned char));
nr->digits = calloc(size, sizeof(unsigned char));
printf("Digits : \n");
bytes_read = fread(digits, size, 1, file);
for(i = 0 ; i < size; i++){
printf("%.2X ", digits[i]);
}
memcpy(nr->digits, digits, size);
free(digits);
return nr;
}
For the following data in Data.bin (Hexdumped):
04 00 00 00 02 00 00 00 00 02 08 03 09 05 03
I get the output:
Bytes read : 1
First index : 4
Bytes read : 1
Second Index : 2
Bytes read : 1
Sign : 00
Digits :
02 08 03 09 05 03
Function to transform Number strunct in float:
double fromNumbertoDouble(Number *number){
int size = 0;
char *buff;
size = number->digitsAfter + number->digitsBefore + 2;
buff = calloc(size, sizeof(char));
if (!buff) {
fprintf(stderr, "Error calloc in fromNumberToDouble");
exit(1);
}
if (number->sign == '01') {
strcat(buff, "-");
}
strncat(buff, number->digits, number->digitsBefore);
strcat(buff, ".");
strncat(buff, number->digits+number->digitsBefore, number->digitsAfter);
return atof(buff);
}
This always return 0.
When I checked to see what is in the number returned from fromBinaryToNumber, number->digits = "\002\b\003\t\005\003".
I'm aware that atof can't convert something like that into a float.
My question is how can i convert the number->digits into something that would get converted into a float by atof.
Any other idea on how to solve this would also be appreciated.
Thank you for your time.
For each of the digits, add '0', i.e. the codepoint value for the digit 0. This turns the array into a a sequence of digit characters. Of course, it must also be 0-terminated for atof(), which requires a proper string.
You do realize that your format is fantastically awkward, right? A single float would use 4 bytes for the entire number, always. If you're going to convert to float anyway you're not going to be able to keep the arbitrary precision that your format supports.
First your buffer size is wrong - you've not taken into account the decimal point, sign or the zero-terminator. Also you don't initialise buff - so strcat may concatenate anywhere- you should either calloc, or memset the buff to 0 before strcat'ing anything to it.