sscanf not detecting the right numbers - c

I'm having a hard time using sscanf to scan hour and minutes from a list. Below is a small snip of the list.
1704 86 2:30p 5:50p Daily
1711 17 10:40a 2:15p 5
1712 86 3:10p 6:30p 1
1731 48 6:25a 9:30a 156
1732 100 10:15a 1:30p Daily
1733 6 2:15p 3:39p Daily
I've tried this, but it keeps getting me segmentation Fault.(I'm putting this information into structures).
for(i=0;i<check_enter;i++){
sscanf(all_flights[i],
"%d %d %d:%d%c %d:%d%c %s",
&all_flights_divid[i].flight_number,
&all_flights_divid[i].route_id,
&all_flights_divid[i].departure_time_hour,
&all_flights_divid[i].departure_time_minute,
&all_flights_divid[i].departure_time_format,
&all_flights_divid[i].arrival_time_minute,
&all_flights_divid[i].arrival_time_minute,
&all_flights_divid[i].arrival_time_format,
&all_flights_divid[i].frequency);
printf("%d ",all_flights_divid[i].flight_number);
printf("%d ",all_flights_divid[i].route_id);
printf("%d ",all_flights_divid[i].departure_time_hour);
printf("%d ",all_flights_divid[i].departure_time_minute);
printf("%c ",all_flights_divid[i].departure_time_format);
printf("%d ",all_flights_divid[i].arrival_time_hour);
printf("%d ",all_flights_divid[i].arrival_time_minute);
printf("%c ",all_flights_divid[i].arrival_time_format);
printf("%s\n",all_flights_divid[i].frequency);
}
This is how I declared it.
struct all_flights{
int flight_number;
int route_id;
int departure_time_hour;
int departure_time_minute;
char departure_time_format;
int arrival_time_hour;
int arrival_time_minute;
char arrival_time_format;
char frequency[10];
};
struct all_flights all_flights_divid[3000];
These are the results I get
1704 86 2 30 p 0 50 p Daily
1711 17 10 40 a 0 15 p 5
1712 86 3 10 p 0 30 p 1
1731 48 6 25 a 0 30 a 156
1732 100 10 15 a 0 30 p Daily
1733 6 2 15 p 0 39 p Daily

Small mistake, that might be the problem:
this:
&all_flights_divid[1].flight_number,
should be:
&all_flights_divid[i].flight_number,
// ^
Edit:
Also, you read arrival_time_minute twice, and not reading arrival_time_hour at all. Fix it and it should be OK.

Most of the results seem to be fine, except the first field.
Now if you check your code..
&all_flights_divid[1]
fix it with
&all_flights_divid[i]

Related

Why does my c code not add the correct null zero at the end like it is supposed to and keeps printing out code?

I do not know why my code does not seem to be working properly. I am reading from a file, and grabbing each line and from there I am using my own function to try and break down each of the lines and add them to character arrays in a structure and then add those structures to an array. But for whatever reason, when I am trying to indivudually print out the individual values for all of the information it keeps printing out all of it. From what I am seeing, for whatever reason even though my function strsub is supposed to add a '\0' at the end, it does not seem to be doing that. So every time I pass in the pointer to the begging of each of the character variables it does not stop until the end of the whole structure so it starts by printing out the whole string and then prints out less and less. Is that the problem that I really have or am I missing something else?
This is my code so far. I first just tried creating a struct and filling the array with each pass, but unfortunantly I had the same issue.
#define _CRT_SECURE_NO_WARNINGS // Since I want to strictly use ANSI C and not Microsoft C without getting the warning message, I'm adding this line of code before I include header files.
#include <stdio.h> // "#include" includes the contents of another file, commonly called header file, into the source code file.
#include <string.h>
#define MAX 100
FILE *fp, *csit;
void strsub(char buf[], char sub[], int start, int end);
void printArray(struct trainCartrain[]);
struct trainCar {
char car[10];
char type[2];
char weight[6];
char length[3];
char horsepower[3];
char numberInTrain[4];
};
int main() {
struct trainCar ar[7];
struct trainCar train;
// test and open input file and output file.;
if (!(fp = fopen("train.txt", "r"))) {
printf("train.txt could not be opened for input.");
exit(1);
}
if (!(csit = fopen("csit.txt", "w"))) {
printf("csit.txt could not be opened for output.");
exit(1);
}
int i = 0;
char buf[MAX];
while (!feof(fp)) {
fgets(buf, MAX, fp);
strsub(buf, train.car, 0, 9);
strsub(buf, train.type, 10, 11);
strsub(buf, train.weight, 12, 17);
strsub(buf, train.length, 18, 20);
strsub(buf, train.horsepower, 21, 23);
strsub(buf, train.numberInTrain, 24, 27);
printf("%s", train.car);
printf("%s", train.type);
ar[i] = train;
i++;
}
printArray(ar);
fclose(csit);
fclose(fp);
return 0;
}
void strsub(char buf[], char sub[], int start, int end) { //strsub () grabs a substring, sub, from a string, buf, given the start and end index within the string.
int i, j;
for (j = 0, i = start; i <= end; i++, j++) {
sub[j] = buf[i];
}
sub[j] = '\0';
//end with the null terminator character that signifies the end of a string.
}
My file is small and simple, textfile
Boxcar D 44000 55 16 45
Hopper B 23000 62 18 33
Tanker G 15000 45 30 12
Autocar A 30000 37 23 6
Livestock L 56500 50 18 19
Coalcar C 49300 53 22 100
Flatcar F 18000 66 15 25
and what it prints out is
Boxcar D 44000 55 16 45
D 44000 55 16 45
44000 55 16 45
55 16 45
16 45
45
Hopper B 23000 62 18 33
B 23000 62 18 33
23000 62 18 33
62 18 33
18 33
33
Tanker G 15000 45 30 12
G 15000 45 30 12
15000 45 30 12
45 30 12
30 12
12
Autocar A 30000 37 23 6
A 30000 37 23 6
30000 37 23 6
37 23 6
23 6
6
Livestock L 56500 50 18 19
L 56500 50 18 19
56500 50 18 19
50 18 19
18 19
19
Coalcar C 49300 53 22 100
Flatcar F 18000 66 15 25C 49300 53 22 100
Flatcar F 18000 66 15 2549300 53 22 100
Flatcar F 18000 66 15 2553 22 100
Flatcar F 18000 66 15 2522 100
Flatcar F 18000 66 15 25100
Flatcar F 18000 66 15 25Flatcar F 18000 66 15 25F 18000 66 15 2518000 66 15 2566 15 2515 2525
can someone please explain what I am doing wrong? I do have to use this function strsub for my class too.
I am just trying to get it to print out the individual charachter data and not the whole string each time. I think it is an issue with the terminating zero at the end and when I tried debugging it does not seem to be adding that for some reason. I don't know why though, if that is the problem.
strsub(buf, train.car, 0, 9); accesses train.car with index 0 till 9 in the loop and then index 10 outside, but that's already out of bounds for a char car[10];.
Solution:
Increase the size of all of your arrays by 1 to have space for the 0-terminator of the string.
Also have a look at Why is “while( !feof(file) )” always wrong? . It is not related to your problem, but you might run into that problem in the next minutes.
Instead of
while (!feof(fp)) {
fgets(buf, MAX, fp);
....
}
use
while (fgets(buf, MAX, fp)) {
....
}
You missed a space in void printArray(struct trainCartrain[]);. It should be void printArray(struct trainCar train[]); and moved to after the definition of struct trainCar.
You also have to #include <stdlib.h> to use exit(1);

C - Any way to initialize srand multiple times?

Is there any way to initialize srand multiple times? I have an specific function to generate random numbers but every time i call it gives the same number. Any way to fix this?
int whoatk2() {
srand(time(NULL));
int a;
a = rand() % 50;
return a;
}
Unless you want a specific sequence, you should be calling srand once, and with a effectively arbitrary value like time(NULL). This would usually be done when your program starts.
If you call it every time you want a random number, you run the very real risk of initialising the generator with the same value each time (if you're calling it many times per second) and therefore getting the same "random" value each time.
This is the sort of thing you should be doing:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
srand(time(NULL)); // do this once
for (int i = 0; i < 10; ++i) { // do this many times
printf("%d\n", rand());
}
return 0;
}
Sample output is shown below, with the left column containing the output for the correct code above, and the right column containing the result of moving the srand call to inside the loop as you currently have (swapping the two lines that have comments above):
966271109 74846356
1059160369 74846356
1868029595 74846356
758240870 74846356
1795677958 74846356
806788680 74846356
1374271653 74846356
1658543317 74846356
1843517305 74846356
1568992484 74846356
srand is the function to initialize the pseudo-random generator with a seed, and rand is the function to get a random number from the generator...
You get the same random number repeatedly because you reinitialize the random number generator with the same seed every time you call whoatk2, which happens many times during the same second. The sequence of pseudo-random numbers returned by rand() is completely determined by the value passed to srand().
You should call srand() just once at the beginning of the program, preferably with a value that varies faster than time(NULL). You can use timespec_get(), gettimeofday() or similar:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#ifdef TIME_UTC
void random_initialize(void) {
struct timespec ts;
timespec_get(&ts, TIME_UTC);
srand(ts.tv_nsec);
}
#else
#include <sys/time.h>
void random_initialize(void) {
struct timeval tv;
gettimeofday(&tv, NULL);
srand(tv.tv_usec);
}
#endif
int whoatk2(void) {
return rand() % 50;
}
int main() {
random_initialize();
for (int i = 0; i < 20; i++) {
printf("%d ", whoatk2());
}
printf("\n");
return 0;
}
Running 10 times:
36 33 35 31 8 32 1 5 30 23 20 8 5 35 47 10 14 26 34 40
32 49 33 16 28 31 22 6 32 33 45 44 17 32 18 38 8 34 28 38
48 38 35 49 25 18 40 3 38 3 36 46 12 26 21 16 15 48 34 39
49 33 9 28 24 39 4 32 33 9 29 23 10 29 41 24 12 33 35 33
5 40 49 16 22 47 27 15 29 39 35 32 28 23 39 35 19 24 10 0
5 45 33 24 4 28 48 40 32 22 27 45 32 11 35 28 0 37 32 9
36 3 38 16 12 25 14 27 30 31 0 49 41 40 39 5 23 26 40 8
11 9 21 15 34 0 13 47 49 47 33 21 3 42 16 19 32 32 33 15
14 2 27 26 19 15 5 41 32 49 48 31 20 12 39 16 15 19 32 20
3 2 34 32 47 24 34 21 0 28 6 48 44 16 6 46 40 48 20 13

Stack Smashing Detected in GCC

I'm new to C and I've found a peculiar output from gcc that I'm having a hard time getting to the bottom of. The error upon running the application is:
*** stack smashing detected ***: /home/joshua/Research/cml/test terminated
Program received signal SIGABRT, Aborted.
0x00007ffff7a43428 in __GI_raise (sig=sig#entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
54 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
I've done some research on this, and it appears that this is many times caused by tying to put too large a value into an array, for example; I'm not doing anything like that.
Here is my sample code for reference:
1 #include <stdio.h>
2 #include <string.h>
3
4 struct student
5 {
6 int id;
7 char name[10];
8 float percentage;
9 };
10
11 int main()
12 {
13 int i;
14 struct student record[2];
15
16 // 1st student's record
17 record[0].id=1;
18 strcpy(record[0].name, "Raju");
19 record[0].percentage = 86.5;
20
21 // 2nd student's record
22 record[1].id=2;
23 strcpy(record[1].name, "Surendren");
24 record[1].percentage = 90.5;
25
26 // 3rd student's record
27 record[2].id=3;
28 strcpy(record[2].name, "Thiyagu");
29 record[2].percentage = 81.5;
30
31 for(i=0; i<3; i++)
32 {
33 printf(" Records of STUDENT : %d \n", i+1);
34 printf(" Id is: %d \n", record[i].id);
35 printf(" Name is: %s \n", record[i].name);
36 printf(" Percentage is: %f\n\n",record[i].percentage);
37 }
38 return 0;
39 }
The 2 in
struct student record[2];
is not the top index, it is the number of elements. And as you seem to know indexes start at zero which means the valid indexes are 0 and 1 for the above array. Going out of bounds leads to undefined behavior.
struct student record[2];
You've got an array of size 2 and you're trying to store 3 elements in it. Array indices go from 0 to n-1. record[2] is an invalid index.
To keep a check on the integrity of the functions, next to the return statement Gcc adds protection variables (called canaries) which have known values.In your case when the uninitialized access is done on record[2] you have violated the stacks integrity and the canary values are overwritten which trigger the crash.

I am trying to set a value to an array, but I can't seem to figure out why what I did on line 31 is wrong

I have a data file in the format <0:00> - <19321> , <1:00> - <19324>, up to <24:00> - <19648>, so for every hour there is the total power used so far(the total is incremented), I am supposed to calculate the power used, find the average, and the highest usage of power and its index(time), (I don't need help with finding the max power used at its time index). I traced the problem down to line 31, but I don't understand why what I did was wrong. Can someone explain to me why the code in line 31 isn't saving the value of power used into the array? And how I can fix it? Thanks in advance!
float compute_usage(int num, int vals[], int use[], int *hi_idx)
15 {
16 int i;// i is a general counter for all for loops
17 int r1, r2, u, v, pow_dif, temp;//for loop 1
18 int tot;//for loop 2
19 int max_use, init, fina, diff;//for loop 3 //don't have to worry about this for loop, I am good here
20 float avg;//average power used
21
22 for(r1=r2=i=u=v=0;i<num;i++)//for loop 1
23 {
24 r1= vals[v++];//I set values of every hour as reading 1 & 2(later)
25 #ifdef DEBUG
26 printf("pre-debug: use is %d\n", use[u]);
27 #endif
28 if(r1!=0 && r2!=0)
29 {
30 pow_dif = (r1 - r2);//I take the to readings, and calculate the difference, that difference is the power used in the interval between a time period
31 use[u++] = pow_dif; //I'm suppose to save the power used in the interval in an array here
32 }
33 r2=r1;//the first reading becomes the second after the if statement, this way I always have 2 readings to calculate the power used int the interval
34 #ifdef DEBUG
35 printf("for1-debug3: pow_dif is %d\n", pow_dif);
36 printf("for1-debug4: (%d,%d) \n", u, use[u]);
37 #endif
38
39 }
40 for(tot=i=u=0;i<num;i++)//for loop 2
41 {tot = tot + use[u++];}
42
43 avg = tot/(num-1);
44 #ifdef DEBUG
45 printf("for2-debug1: the tot is %d\n", tot);
46 printf("for2-debug2: avg power usage is %f\n", avg);
47 #endif
Just to understand, how did you figure out that the code in line 31 is problematic? Is it the printf statement in line 36?
When you do this:
use[u++] = pow_dif; //I'm suppose to save the power used in the interval in an array here
printf("for1-debug4: (%d,%d) \n", u, use[u]);
The "u" variable in printf statement is incremented in the previous operation (u++), so you are looking past the element you changed.
use[u++] = pow_dif; //I.e. u=0 here, but u=1 after this is executed.
printf("...\n", u=1, use[1]);
What is the "i" for in this loop? Why don't you try "u++" in the for statement instead of "i++" and remove the "u++" in the use assignment expression?

global variable is not incrementing properly

int count;
int main(){
count=0;
printf("%6d\t %6d\t %6d\t ",i+1,multiFib(i),count);
}
int multiFib(int x){
if (x<2){
return 1;
count++;
}}
In this code, count always gives 0 result. I made it a global variable, not to define it in the function again. How can I increase that variable?
It outputs in order; that is not problem. It gives the result:
1 1 0
-
2 1 0
-
3 2 0
So, count is not increasing — but why?
Although order of evaluation is not guaranteed (see multiple other answers), there is another, more fundamental problem (actually, two of them):
int multiFib(int x)
{
if (x<2){
return 1;
count++;
}
}
You attempt to increment count after you've returned from your function. Your compiler should be warning about unreachable code.
You don't return a value from multiFib() when the input is bigger than 2.
The fragment of main() that you show references an undefined variable i. I assume that is because you deleted a for (i = 0; i < 40; i++) loop from before the printf() statement. To fix the 'order of evaluation' problem, you might want to use:
int count;
int main(void)
{
for (int i = 0; i < 40; i++)
{
count = 0;
int fib = multiFib(i);
printf("%3d %10d %10d\n", i+1, fib, count);
}
return(0);
}
This evaluates the number of calls to multiFib() for each top-level call to the function.
For the multiFib() function itself, you probably need:
int multiFib(int x)
{
count++;
if (x < 2)
return x;
else
return multiFib(x-1) + multiFib(x-2);
}
Though this is an appallingly slow implementation of Fibonacci numbers so you shouldn't use this as an answer to your homework (but it does make a 'working' function).
Example output:
1 0 1
2 1 1
3 1 3
4 2 5
5 3 9
6 5 15
7 8 25
8 13 41
9 21 67
10 34 109
11 55 177
12 89 287
13 144 465
14 233 753
15 377 1219
16 610 1973
17 987 3193
18 1597 5167
19 2584 8361
20 4181 13529
21 6765 21891
22 10946 35421
23 17711 57313
24 28657 92735
25 46368 150049
26 75025 242785
27 121393 392835
28 196418 635621
29 317811 1028457
30 514229 1664079
31 832040 2692537
32 1346269 4356617
33 2178309 7049155
34 3524578 11405773
35 5702887 18454929
36 9227465 29860703
37 14930352 48315633
38 24157817 78176337
39 39088169 126491971
40 63245986 204668309
Note that if you go much beyond 40, you start getting arithmetic overflow. It also gets to be very (very, very) slow.
This:
if (x<2){
return 1;
count++;
}
You return from the function before you increment count. So it's never incremented.
Return doesn't just set the returned value. It actually exits the function at that point.
Just swap the order of those two lines. Also, you should keep an eye on your compiler warnings. Any decent compiler will warn you that the count++; line is unreachable.
printf("%6d\t %6d\t %6d\t ",i+1,multiFib(i),count);
The order of function argument evaluation is unspecified in C. multiFib can be evaluated before or after count in the printf function call.
The order of evaluation of function arguments is not specified.
In your code,
printf("%6d\t %6d\t %6d\t ",i+1,multiFib(i),count);
The argument to printf function multiFib(i) might be getting called after printing count.
Try this,
printf("%6d\t",multiFib(i));
printf("%6d\t %6d\t ",i+1,count);
to check the result.
As it was said in another answers, problem is that order of evaluation of function arguments is not specified, so in your example:
printf("%6d\t %6d\t %6d\t ",i+1,multiFib(i),count);
You can not be sure if count will be evaluated before or after passing multiFib(i) to the printf() function.
Please look here for more detailed information about evaluation order in C++, or here for evaluation order in C.
You might also find useful to force evaluation order by separating your printf into two calls:
printf("%6d\t",multiFib(i));
printf("%6d\t %6d\t ",i+1,count);
like Nishith Jain M R suggested in his answer.

Resources