How do I sscan for time? - 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[1].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
0 86 2 30 p 0 50 p Daily
0 17 10 40 a 0 15 p 5
0 86 3 10 p 0 30 p 1
0 48 6 25 a 0 30 a 156
0 100 10 15 a 0 30 p Daily
0 6 2 15 p 0 39 p Daily

Look carefully at your list of output targets in sscanf. Do you see the difference between &all_flights_divid[i].departure_time_minute and all_flights_divid[i].departure_time_format? Similary for .arrival_time_format and .frequency.
What do you think the & ampersand is for? Hint: what is one way of returning multiple values from a single function call, and what does this have to do with the & ampersand?
A segmentation fault arises when your program tries to write data into memory the operating system has never instructed the CPU to make available to the program. Segmentation faults do not always occur when data is misplaced, because sometimes data is misplaced within available memory. By way of analogy, if you inadvertently put a book in the wrong place on the bookshelf, you'll not easily find the book later, but the book is still on a bookshelf and does not seem to anyone to be out of place. On the other hand, if you inadvertently put the same book in the refrigerator, well, when mother goes to get the milk she's going to issue you a segmentation fault! That's the analogy, anyway.
In general, it is hard to guess whether misplacing data will cause a segmentation fault (as misplaced into the refrigerator) or not (as misplaced on the bookshelf) until you run the program. The segmentation fault (refrigerator) is preferable because it makes the mistake obvious, so the operating system tries to give you as many segmentation faults as it can by affording the program as little memory as possible.
I am avoiding giving a 100 percent direct answer because of your "homework" tag. See if you cannot figure out the & ampersand matter, then come back here if it still does not make sense.

Your pointers are all messed up. Perhaps a series of local variables specifically for reading this stuff in would help you organize this all in your head.
int flightNum, routeID, depHour, depMin, arrHour, arrMin;
char depFormat, arrFormat;
char * freq;
for(i=0;i<check_enter;i++){
sscanf(
all_flights[i],"%d %d %d:%d%c %d:%d%c %s"
&flightNum, &routeID,
&depHour, &depMin, &depFormat,
&arrHour, $arrMin, $arrFormat,
freq
);
all_flights_divid[i].flight_number = flightNum;
all_flights_divid[i].route_id = routeID;
all_flights_divid[i].departure_time_hour = depHour;
all_flights_divid[i].departure_time_minute = depMin;
all_flights_divid[i].departure_time_format = depFormat;
all_flights_divid[i].arrival_time_hour = arrHour;
all_flights_divid[i].arrival_time_minute = arrMin;
all_flights_divid[i].arrival_time_format = arrFormat;
strcpy(all_flights_divid[i].frequency, freq);
}

Related

Data Validation for the number of arguments not changing value

I have this code that needs to take in 3 command line arguments that are numbers in order to convert from Fahrenheit to Celsius. I have everything working in the program but I am having issues with changing the 'step' variable to int 1 if it is not specified as an argument when running the program. I added the if statement to check if the argument exists and then have that change the value to one if it does not but it returns a segmentation fault. Here is the if statement:
int step = atoi(argv[3]);
if(argc == 2){
step = 1;
return step;
}
Here are the results of running the program:
root#computer:/home/sus/cyb126/homework$./temperature_chart 32 212
Segmentation fault (core dumped)
root#computer:/home/sus/cyb126/homework$./temperature_chart 32 212 20
32 0.000000
52 11.111111
72 22.222221
92 33.333332
112 44.444443
132 55.555557
152 66.666664
172 77.777779
192 88.888885
212 100.000000
I don't understand why it returns a segmentation fault by compiles fine with no warnings. I can only think that it does not listen to the if statement for some reason.
Appreciate any help.
Changed code to the following after I was answered with good advice below:
int step;
if (argc == 2) {
step = atoi(argv[3]);
}
else {
step = 1;
}
When you pass 2 arguments the argv array is only 3 elements long ( the number of elements is always argc+1). This means that by accessing argv[3] you are accessing the fourth element of a three element vector. This is an out of bound access and you get a seg fault.

How can I know why a program causes a coredump sigfault?

I have those functions and I would like to know if anyone can help me. I have to investigate why they cause a "segfault", and why it happens faster or slower depending on its conditions.
I supposed that in Rec1, it's caused by an infinite loop that collapses the memory of the memory stack. In rec2 I suppose it's caused faster because of the same condition that in Rec1 but adding that it is allocating memory everytime for the pointer too.
In Rec3 () that crashes instantly because it's allocating the same memory spot in the second iteration and causes a problem because the program is trying to access the same allocated memory.
In Rec4 () I think it's caused because it creates an array with infinite positions, ask is the limiting of the array max space.
Can you give me some advices on those suppositions?
#include <stdio.h>
#include <stdlib.h>
#define MOD 10000
int k = 0;
char global[100];
void
panic (char *m)
{
fprintf (stderr, "%s\n", m);
exit (0);
}
void
rec1 ()
{
k++;
if (k % MOD == 0)
fprintf (stderr, "%d ", k / MOD);
rec1 ();
}
void
rec2 ()
{
int *tmp;
tmp = malloc (100 * sizeof (int));
if (tmp == NULL)
exit (0);
k++;
if (k % MOD == 0)
fprintf (stderr, "%d ", k / MOD);
rec2 ();
}
void
rec3 ()
{
int tmp[100];
k++;
if (k % MOD == 0)
fprintf (stderr, "%d ", k / MOD);
rec3 ();
}
void
rec4 ()
{
global[k] = k;
if (k % 200 == 0)
fprintf (stderr, "%d ", k);
k++;
rec4 ();
}
int
main (int argc, char *argv[])
{
int mode = 1;
if (argc > 1)
mode = atoi (argv[1]);
printf ("Testing rec%d...\n", mode);
switch (mode)
{
case 1:
rec1 ();
break;
case 2:
rec2 ();
break;
case 3:
rec3 ();
break;
case 4:
rec4 ();
break;
default:
panic ("Wrong mode");
}
return 0;
}
This is the output when I run the compiled C program in terminal.
Testing rec1...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
Program received signal SIGSEGV, Segmentation fault.
0x0000555555554904 in rec1 () at stack.c:24
24 rec1 ();
Testing rec2...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7a7b96a in __GI___libc_free (mem=0x555555757670) at malloc.c:3086
3086 malloc.c: No existe el archivo o el directorio.
Testing rec3...
1
Program received signal SIGSEGV, Segmentation fault.
0x0000555555554a43 in rec3 () at stack.c:53
53 rec3 ();
Testing rec4...
0 200 400 600 800 1000 1200 1400 1600 1800 2000 2200 2400 2600 2800 3000 3200 3400 3600 3800 4000 ViolaciĆ³n de segmento (`core' generado)
Program received signal SIGSEGV, Segmentation fault.
0x0000555555554a1f in rec4 ()
The Code that you have is very likely to trigger an error in my experience. Without any compiler or program feedback, it's a little difficult to discern exactly what went wrong, but I believe you may be looking (Generally) for information regarding stacks, heaps, and recursion.
Firstly, please note that
void rec1 () {
k++;
if (k % MOD == 0)
fprintf (stderr, "%d ", k / MOD);
rec1 ();
}
is NOT "Iteration". Iteration refers to the repetition of a sequential portion of code (usually a for or while loop). What you have here is recursion. Recursion creates a new instance of the method to operate from, along with a stack pointer to navigate to the last execution point (As well as store any immediately relevant variables). This occurs every time you call the rec1 () function from your rec1 () function Eventually, you'll run out of space on the stack to store those pointers. The number of pointers you can store on a stack is usually quite large on modern computers, but considering that you have no return statement, you will run into the maximum capacity eventually.
EDIT
This post has been edited to reflect the new material presented by the question.
Okay...From the material you presented, it looks like you're essentially being asked about WHERE each rec stores and processes information...
In the case of Rec1, it does indeed appear to be a simple case of stack overflow. The pointer to the last execution point of the previous Rec1 is stored on the stack, ultimately resulting in the program's crash after about 520,000 instances. Given that each pointer is 4 bytes, that's around 2 MB of just recursive pointer information alone stored on your stack before it collapses and triggers a Seg Fault due to stack overflow.
The second case is a little trickier. Note that your program indicates that it makes it to roughly 260,000 recursions before it triggers a Seg Fault. This is exactly half of Rec1. HOWEVER, this is not necessarily a stack overflow per se. Rec2 allocates 400 bytes of data on the heap per recursion. The pointer to the heap is stored on the stack, meaning that 8 bytes are stored on the stack per recursion (which may be related to why its exactly half, but could also be explained by the ratio of your stack / heap size). Now, the error for Rec2 states that malloc could not find the file or directory, which seems to me as though malloc could not complete correctly. This may actually indicate that the max heap size has been hit.
Rec3 is pretty straightforward. The entire integer array tmp is stored on the stack for each recursion. that's 4 bytes per integer times 100 ints, which is 400 bytes on the stack PER recursion. This is no surprise that it crashes between 10,000 to 20,000 recursions. There just wasn't enough space to store the data on the stack. NOTE: In relation to something you mentioned in your question, this tmp array does not attempt to allocate the same region of memory. Due to the fact that this is recursively built, it creates a new space on the stack for that function instance.
Rec4 is a simple case of buffer overflow. After overwriting the first 100 bytes of memory allocated in global[100], it was only a matter of time before k++ would cause global[k] to point to an address space restricted to the process. This triggered the seg fault after about 4000 recursions (k was not mod 10,000 in rec4).
I hope this clarification helps.

Reading bytes from progmem

I'm trying to write a simple program (as a pre-cursor to a more complicated one) that stores an array of bytes to progmem, and then reads and prints the array. I've looked through a million blog/forums posts online and think I'm doing everything fine, but I'm still getting utter gibberish as output.
Here is my code, any help would be much appreciated!
void setup() {
byte hello[10] PROGMEM = {1,2,3,4,5,6,7,8,9,10};
byte buffer[10];
Serial.begin(9600);
memcpy_P(buffer, (char*)pgm_read_byte(&hello), 10);
for(int i=0;i<10;i++){
//buffer[i] = pgm_read_byte(&(hello[i])); //output is wrong even if i use this
Serial.println(buffer[i]);
}
}
void loop() {
}
If I use memcpy, I get the output:
148
93
0
12
148
93
0
12
148
93
And if I use the buffer = .... statement in the for loop (instead of memcpy):
49
5
9
240
108
192
138
173
155
173
You're thinking about two magnitudes too complicated.
memcpy_P wants a source pointer, a destination pointer and a byte count. And the PROGMEM pointer is simply the array. So, your memcpy_P line should like like
memcpy_P (buffer, hello, 10);
that's it.
memcpy (without the "P") will not be able to reach program memory and copy stuff from data RAM instead. That is not what you want.

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.

C program to check lottery numbers: why some tests fail?

This program takes as an input the following lines:
23 12 33 19 10 8
5
23 19 8 12 60 18
14 60 12 44 54 10
8 3 12 19 33 10
33 15 7 60 12 10
22 12 19 23 33 11
23 12 33 19 10 8 ( The first line ) are the lottery results.
n ( in this specific case, 5 ) informs how many lines will follow below.
Each line has 6 numbers. The number order doesn't matter.
The rules are: numbers range from 1 to 60 ( including 1 and 60 ) and they never repeat themselves in the same line.
The variable "quadra" stores how many lines have got 4 numbers right.
The variable "quina" stores how many lines have got 5 numbers right.
The variable "sena" stores how many lines have got 6 numbers right.
So, a computer program is running some tests over my code below and it's claiming that it goes wrong for most of them, but I can't see what's the problem here. Does anybody have a clue? Is this code wrong, or is there something wrong with the software that's testing this code?
#include <stdio.h>
int main(){
int mega[6];
int v[50500][6];
int n,swap;
int i,j,k; //counters
int quadra,quina,sena;
quadra = 0;
quina = 0;
sena = 0;
for(i=0;i<6;++i) scanf("%i",&mega[i]); //first line, lottery results
scanf("%i",&n);
for(i=0;i<n;++i){
for(j=0;j<6;++j){
scanf("%i",&v[i][j]);
}
}
for(i=0;i<n;++i){
for(j=0;j<6;++j){
for(k=0;k<6;++k){
if(v[i][j] == mega[k]){
v[i][j] = 61;
}
}
}
}
//reverse bubble sort
for(i=0;i<n;++i){
for(j=0;j<6;++j){
for(k=j+1;k<6;++k){
if(v[i][j] < v[i][k]){
swap = v[i][k];
v[i][k] = v[i][j];
v[i][j] = swap;
}
}
}
}
for(i=0;i<n;++i){
for(j=0;v[i][j] == 61 && j<6;++j);
if(j == 4) ++quadra;
else if(j == 5) ++quina;
else if(j == 6) ++sena;
}
return 0;
}
Your code is true, I understood and tried the flow of it. Looks fine but if you dont need to sort everyline (and use j as a counter in this loop for(j=0;v[i][j] == 61 && j<6;++j); ), you can use simpler ifstatements to compare real lottery results with the ones that entered. What I mean is that your algorithm is a little complex. Try a simple one and see how it works.
Yes, there are a couple of noteworthy issues with your code:
Compile time indicates possibility of uninitialized variable:
But, run-time results in fatal run-time at unknown source location. Stack overflow. It is likely due to this line:
int v[50500][6];
Increase your stack size. It needs to be about 2.5Mbytes for v alone.
Also, this line may not be what you intended:
for(i=0;i<6;++i) scanf("%i",&mega[i]); //first line, lottery results
^
If you meant to loop around the remainder of the code, remove the ; after the for() statement, and use curly braces:
for(i=0;i<6;++i) scanf("%i",&mega[i]) //first line, lottery results
{
scanf("%i",&n);
....

Resources