Runtime error, input string in array - c

This is the input strings and the code that is supposed to read the file. When I compile using the lastest Dev C++ at home, it runs perfectly. But the Dev C++ at my school crashes the program (and after debug I know it is) at i = 9. Which is this line Michael Nguyen 71 70 91 93 28.
I fixed it by changing char studentFirst[15] to char studentFirst[17]. However the name that is supposed to be put in Michael and Nguyen aren't more than 14 char each. Could someone help me take a look at it. Did I understand something wrong this line fscanf(inFile, "%s%s", studentFirst, studentLast)?
Input:
Sidra Amartey 90 88 70 74 70
Rebecca Brown 85 98 73 78 74
Leslie Carter 92 73 86 36 87
Ashley Guillen 95 26 90 83 85
Ryan Hilliard 75 66 69 100 52
Dawn Hopkins 84 69 66 88 74
Kyle Jiwani 7 99 96 84 89
Melvin Johnson 73 80 63 38 88
Edward Maun 82 85 72 75 99
Angelo Morrison 95 97 80 31 70
Michael Nguyen 71 70 91 93 28
Zack Nutt 82 85 97 74 98
Diana Patel 77 70 88 68 82
Patrick Perez 87 77 21 88 7
Abigail Peterson 64 81 75 85 70
Jennifer Putnam 39 91 85 80 70
Kimberly Sanjel 64 69 74 97 12
Marisa Santos 63 77 90 15 60
Hannah Shrestha 13 77 95 97 99
Linda Stoll 50 85 72 91 23
Victoria Taylor 95 93 74 63 90
Haily Wright 80 90 99 68 84
Code:
int loadStudentNamesGrades(studentnode students[], const char * fileName)
{
FILE * inFile;
char studentFirst[15] = {0};
char studentLast[15] = {0};
int numStudents = 0;
int i = 0, j = 0;
if((inFile = fopen(fileName, "r")) == NULL)
{
printf("Cannot access file %s\n", fileName);
system("PAUSE");
exit(1);
}
for(i = 0; i < MAX_STUDENTS && (fscanf(inFile, "%s%s", studentFirst, studentLast) == 2); i++, numStudents++)
{
for(j = 0; j < MAX_GRADES; j++)
{
fscanf(inFile, "%d", &students[i].grades[j]);
}
students[i].name = (char*)malloc(strlen(studentFirst) + strlen(studentLast) + 2);
strcpy(students[i].name, strcat(strcat(studentFirst, " "), studentLast));
}
return numStudents;
}

Your problem is undefined behavior. First you forget to count the terminating \0, so Michael Nguyen is actually 15 chars, not 14. However your crash is the result of the previous line there Angelo Morrison is 16 long, more than studentFirst can hold! And Abigail Peterson is 17 long, so studentFirst needs to be 17 long. studentLast only needs to be 9, but that is not a problem.
It does not appear that you have understood fscanf wrong. You might not understand that strcat uses studentFirst to hold the full name.

Related

C return big number confusion

When I input the string instead of y or n in this code, it will return the large number.
So I want to know how to fix it.
My first thought is that if I input the string instead of this,
it will return to the first paragraph and run again.
But when I trying to use this, it will return and run again.
But It will save the string and change it into an ASCII code.
#include <stdlib.h>;
#include <stdio.h>;
int main() {
int num = 1; //設置迴圈變數
int change; //設置可變動變數
int count=0; // 跑了幾次
char ans1,ans2,ans3,ans4,ans5,ans6,ans7 ; //答案共7個
int final_ans = 0;//最後答案
printf("thinking a number on your mind, and I will guess it!\n\n");
first:
for(num=1; num<=100; num+=2) {
++count;
printf("%-4.2d", num);//4格寬 數字顯示2位
if(count%9==0) {
printf("\n");//每執行9次換行
}
}
count = 0;//清空變數
printf("\n");
printf("Is your number on the table (y/n)? \n");
scanf("%s", &ans1);
if((ans1=='Y') || (ans1=='y')) { //若有數字
final_ans += 1;
}
second:
for(num=2; num<=100; num+=2) {
change = num;
++count;
if(count%2==0) {
change--;
}
printf("%-4.2d", change);//4格寬 數字顯示2位
if(count%9==0) {
printf("\n");//每執行9次換行
}
}
printf("\n");
printf("Is your number on the table (y/n)? \n");
scanf("%s", &ans2);
count = 0;//清空變數
change = 0;//清空變數
if((ans2=='Y') || (ans2=='y')) {
final_ans += 2;
}
third:
for(num=4; num<=100; num++) {
change = num;
++count;
if(count%4==1&&num!=4) {
num+=4;
}
printf("%-4.2d", num);//4格寬 數字顯示2位
if(count%9==0) {
printf("\n");//每執行9次換行
}
}
printf("\n");
printf("Is your number on the table (y/n)? \n");
scanf("%s", &ans3);
count = 0;//清空變數
change = 0;//清空變數
if((ans3=='Y') || (ans3=='y')) {
final_ans +=4;
}
fourth:
for(num=8; num<=100; num++) {
change = num;
++count;
if(count%8==1&&num!=8) {
num+=8;
}
if(num>100) {
break;
}
printf("%-4.2d", num);//4格寬 數字顯示2位
if(count%9==0) {
printf("\n");//每執行9次換行
}
}
printf("\n");
printf("Is your number on the table (y/n)? \n");
scanf("%s", &ans4);
count = 0;//清空變數
change = 0;//清空變數
if((ans4=='Y') || (ans4=='y')) {
final_ans += 8;
}
fifth:
for(num=16; num<=100; num++) {
change = num;
++count;
if(count%16==1&&num!=16) {
num+=16;
}
if(num>100) {
break;
}
printf("%-4.2d", num);//4格寬 數字顯示2位
if(count%9==0) {
printf("\n");//每執行9次換行
}
}
printf("\n");
printf("Is your number on the table (y/n)? \n");
scanf("%s", &ans5);
count = 0;//清空變數
change = 0;//清空變數
if((ans5=='Y') || (ans5=='y')) {
final_ans += 16;
}
sixth:
for(num=32; num<=100; num++) {
change = num;
++count;
if(count%32==1&&num!=32) {
num+=32;
}
if(num>100) {
break;
}
printf("%-4.2d", num);//4格寬 數字顯示2位
if(count%9==0) {
printf("\n");//每執行9次換行
}
}
printf("\n");
printf("Is your number on the table (y/n)? \n");
scanf("%s", &ans6);
count = 0;//清空變數
change = 0;//清空變數
if((ans6=='Y') || (ans6=='y')) {
final_ans += 32;
}
seventh:
for(num=64; num<=100; num++) {
++count;
printf("%-4.2d", num);//4格寬 數字顯示2位
if(count%9==0) {
printf("\n");//每執行9次換行
}
}
printf("\n");
printf("Is your number on the table (y/n)? \n");
scanf("%s", &ans7);
if((ans7=='Y') || (ans7=='y')) {
final_ans += 64;
}
else if((ans1=='n') || (ans1=='N')) { //若無數字
final_ans += 0;
goto second;//回到第二個table
} else if((ans2=='n') || (ans2=='N')) { //若無數字
final_ans += 0;
goto third;//回到第三個table
} else if((ans3=='n') || (ans3=='N')) { //若無數字
final_ans += 0;
goto fourth;//回到第四個table
} else if((ans4=='n') || (ans4=='N')) { //若無數字
final_ans += 0;
goto fifth;//回到第五個table
} else if((ans5=='n') || (ans5=='N')) { //若無數字
final_ans += 0;
goto sixth;//回到第六個table
} else if((ans6=='n') || (ans6=='N')) { //若無數字
final_ans += 0;
goto seventh;//回到第七個table
} else if((ans7=='n') || (ans7=='N')) { //若無數字
final_ans += 0;
}
if(final_ans<=100) { //判斷最後答案
printf("your secret number is %d",final_ans);
} else if(final_ans>100) {
printf("WRONG!%d is not a number form 1~100",final_ans);
}
}
you have put ; after every library please remove that
#include <stdlib.h>; // remove the ;
#include <stdio.h>; // remove the ;
correct code must be
#include <stdlib.h>
#include <stdio.h>
By editing that I got correct answers. it works for me.
I have think about 73
output -:
thinking a number on your mind, and I will guess it!
01 03 05 07 09 11 13 15 17
19 21 23 25 27 29 31 33 35
37 39 41 43 45 47 49 51 53
55 57 59 61 63 65 67 69 71
73 75 77 79 81 83 85 87 89
91 93 95 97 99
Is your number on the table (y/n)?
y
02 03 06 07 10 11 14 15 18
19 22 23 26 27 30 31 34 35
38 39 42 43 46 47 50 51 54
55 58 59 62 63 66 67 70 71
74 75 78 79 82 83 86 87 90
91 94 95 98 99
Is your number on the table (y/n)?
n
04 05 06 07 12 13 14 15 20
21 22 23 28 29 30 31 36 37
38 39 44 45 46 47 52 53 54
55 60 61 62 63 68 69 70 71
76 77 78 79 84 85 86 87 92
93 94 95 100
Is your number on the table (y/n)?
n
08 09 10 11 12 13 14 15 24
25 26 27 28 29 30 31 40 41
42 43 44 45 46 47 56 57 58
59 60 61 62 63 72 73 74 75
76 77 78 79 88 89 90 91 92
93 94 95
Is your number on the table (y/n)?
y
16 17 18 19 20 21 22 23 24
25 26 27 28 29 30 31 48 49
50 51 52 53 54 55 56 57 58
59 60 61 62 63 80 81 82 83
84 85 86 87 88 89 90 91 92
93 94 95
Is your number on the table (y/n)?
n
32 33 34 35 36 37 38 39 40
41 42 43 44 45 46 47 48 49
50 51 52 53 54 55 56 57 58
59 60 61 62 63 96 97 98 99
100
Is your number on the table (y/n)?
n
64 65 66 67 68 69 70 71 72
73 74 75 76 77 78 79 80 81
82 83 84 85 86 87 88 89 90
91 92 93 94 95 96 97 98 99
100
Is your number on the table (y/n)?
n
64 65 66 67 68 69 70 71 72
73 74 75 76 77 78 79 80 81
82 83 84 85 86 87 88 89 90
91 92 93 94 95 96 97 98 99
100
Is your number on the table (y/n)?
y
your secret number is 73

What's wrong with the matrix?

What's wrong with this code?
My task is: Create a square matrix of integers with a size of 9x9. Fill the matrix with random numbers. Display the main and side diagonal symmetrically with respect to the vertical axis. The example of expected result is here: matrix
Matrix :
20 20 76 65 93 76 16 2 85
6 87 78 43 48 81 71 90 38
10 12 35 77 48 88 24 53 7
12 66 51 35 74 7 30 22 49
58 14 71 46 68 68 10 81 51
98 16 74 47 64 25 17 30 37
2 44 44 74 34 54 86 73 28
85 4 57 75 18 28 51 76 2
35 17 53 76 15 91 83 85 72
The main and side diagonal:
85 20 76 65 93 76 16 2 20
6 90 78 43 48 81 71 87 38
10 12 24 77 48 88 35 53 7
12 66 51 7 74 35 30 22 49
58 14 71 46 68 68 10 81 51
98 16 74 25 64 47 17 30 37
2 44 86 74 34 54 44 73 28
85 76 57 75 18 29 51 4 2
72 17 53 76 15 91 83 85 35
But in fact the program prints only the main matrix with random numbers and after that stops.
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <Windows.h>
int main()
{
int a = 9;
int matrix[a][a];
int temp;
int i, j, n;
srand((unsigned)time(NULL));
printf("Matrix : \n\n");
for (i = 0; i < a; ++i) {
for (j = 0; j < a; ++j) {
matrix[i][j] = rand() % 100;
printf("%d\t", matrix[i][j]);
}
printf("\n\n");
}
printf("The main and side diagonal:\n\n");
for (i = 0; i < a; ++i) {
temp = matrix[i][i];
matrix[i][i] = matrix[i][(a - 1) - i];
matrix[i][(a - 1) - i] = temp;
}
for (i = 0; i < a; ++i) {
for (j = 0; j < a; ++j) {
printf("Result:", matrix[i][j]);
printf("\n\n\n");
system("pause");
return 0;
}
}
}
You are returning where you are not supposed to. (in middle of the calculation). You should return after you end up working on the for loops.
for (i = 0; i < a; ++i) {
for (j = 0; j < a; ++j) {
printf("Result:", matrix[i][j]); <--- Not printing element
printf("\n\n\n");
system("pause");
return 0; <-----
}
}
It should be
for (i = 0; i < a; ++i) {
for (j = 0; j < a; ++j) {
printf("Result: %d ", matrix[i][j]); <----You forgot the
//format specifier
printf("\n\n\n");
system("pause");
}
}
return 0;<-----
Readability is hampered when the indentation is like this. You implemented wrong logic out of it.
OP asks that it stops after printing "Result" that is because you forgot to put the format specifier in the code. That's why none of the element is printed.
Op wants to print the main and side diagonal symmetrically with respect to the vertical axis.
Now this is everything to with the print part.
Now we have to find a way that will let us distinguish which one is diagonal element and which one is not.
Suprisingly the answer should be known to someone who is writing the previous swapping logic. (Though it is not clear why OP swapped it).
Now all element matrix[p][q] will be from either diagonal if p=q or p+q=a-1. (Note that matrix is a square matrix).
But OP meant to print the matrix
for (i = 0; i < a; ++i) {
if( i == 0) printf("The main and side diagonal : \n");
for (j = 0; j < a; ++j) {
printf("%d\t", matrix[i][j]);
}
printf("\n");
}
}
Use functions. You print the matrix twice; you should have a function to print the matrix which you call twice.
With such a function, you'd not make the mistakes in the tail end of your code. For example, you could use this:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
static void print_matrix(const char *tag, int size, int matrix[size][size])
{
printf("%s (%dx%d):\n\n", tag, size, size);
for (int i = 0; i < size; ++i)
{
const char *pad = "";
for (int j = 0; j < size; ++j)
{
printf("%s%-2d", pad, matrix[i][j]);
pad = " ";
}
printf("\n\n");
}
}
int main(int argc, char **argv)
{
unsigned seed = time(0);
int a = 9;
int matrix[a][a];
if (argc == 2)
seed = atoi(argv[1]);
srand(seed);
printf("Seed: %u\n", seed);
for (int i = 0; i < a; ++i)
{
for (int j = 0; j < a; ++j)
matrix[i][j] = rand() % 100;
}
print_matrix("Matrix", a, matrix);
for (int i = 0, j = a - 1; i < a; ++i, --j)
{
int temp = matrix[i][i];
matrix[i][i] = matrix[i][j];
matrix[i][j] = temp;
}
print_matrix("The main and side diagonal", a, matrix);
return 0;
}
The code reports the seed it uses; that allows you to reproduce any run by specifying the seed to use as a command line argument.
Example output:
Seed: 1511470282
Matrix (9x9):
11 39 3 88 98 63 75 81 76
93 9 60 22 45 50 46 58 65
13 99 25 43 14 57 44 70 65
30 57 55 0 37 84 47 49 40
60 28 46 1 96 78 33 20 9
93 61 11 38 84 16 91 26 15
43 85 66 72 85 39 96 45 45
45 25 33 3 78 90 61 65 62
88 84 56 34 74 8 78 57 74
The main and side diagonal (9x9):
76 39 3 88 98 63 75 81 11
93 58 60 22 45 50 46 9 65
13 99 44 43 14 57 25 70 65
30 57 55 84 37 0 47 49 40
60 28 46 1 96 78 33 20 9
93 61 11 16 84 38 91 26 15
43 85 96 72 85 39 66 45 45
45 65 33 3 78 90 61 25 62
74 84 56 34 74 8 78 57 88
The swapping process, in case it isn't obvious, swaps the first and last elements of the first row, the second and last but one element in the second row, and so on, forming an X of swapped elements.

Issue with fscanf reading input file

I am trying to convert an input file from .txt to .csv. I've performed multiple tests using gdb and switched my code around. The code looks like it should work but for some reason it doesn't. I've tried using "while (fscanf(…arguments…) != EOF)" but I always end up in a never-ending loop when I know that the input file does end. Is it the way I'm trying to read the file that's the problem or something else? I'd greatly appreciate any advice.
A sample of the input file (it's way too big. Also the potentiometer value is the only value that is consistently zero. All other values are greater than zero)
time: 40 ms
switch0: 1
switch1: 1
switch2: 1
switch3: 1
potentiometer: 0.00
temperature: 0.66
light: 0.23
---------------------------
time: 80 ms
switch0: 1
switch1: 1
switch2: 1
switch3: 1
potentiometer: 0.00
temperature: 0.66
light: 0.23
---------------------------
time: 120 ms
switch0: 1
switch1: 1
switch2: 1
switch3: 1
potentiometer: 0.00
temperature: 0.66
light: 0.23
---------------------------
The file that convert from txt to csv
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 int main()
5 {
6 FILE *data = fopen("data.csv","w");
7 FILE *arduino = fopen("arduino.txt","r");
8
9 if(arduino == NULL)
10 {
11 printf("error reading file\n");
12 return 1;
13 }
14 if(data == NULL)
15 {
16 printf("error writing file\n");
17 return 2;
18 }
19
20 fprintf(data,"Time,Switch0,Switch1,Switch2,Switch3,Potentiometer,Temperature,Light\n");
21
22 int num1,num2,num3,num4,num5;
23 double num6,num7,num8;
24
25 double temp1[800];
26
27 int count1 = 0;
28
29 while(count1<800)
30 {
31 fscanf(arduino,"%lf",&temp1[count1]);
32 count1++;
33 }
34
35 for(count1 = 0; count1 < 800; count1++)
36 {
37 printf("%lf",temp1[count1]);
38 }
39
40
41 int count2 = 0;
42 int i = 0;
43
44 while(count2 != 800)
45 {
46 for(i=0 ; i <8;i++)
47 {
48 if(i==7)
49 {
50 fprintf(data,"%lf\n",temp1[count2]);
51 }
52
53 else
54 {
55 fprintf(data, "%lf,", temp1[count2]);
56 }
57 count2++;
58 }
59 }
60
61
62 if (fclose(arduino)==EOF)
63 {
64 printf("error closing input file\n");
65 }
66 if(fclose(data)==EOF)
67 {
68 printf("error closing output file\n");
69 }
70 }
and here's the output
Time,Switch0,Switch1,Switch2,Switch3,Potentiometer,Temperature,Light
2 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
3 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
4 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
5 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
6 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
7 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
8 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
9 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
(still zeros across the board)
61 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
62 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
63 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
64 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
65 0.000000,0.000000,0.000000,0.000000,-nan,0.000000,0.000000,0.000000
66 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
67 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
68 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
69 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
70 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
71 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
72 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
73 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
74 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
75 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
76 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
77 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
78 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
79 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
80 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
81 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
82 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
83 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
84 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
85 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
86 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
87 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
88 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
89 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
90 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
91 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
92 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
93 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
94 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
95 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
96 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
97 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
98 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
99 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
100 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,253700437344304240814662650531587413567701629019053044079803999006261210888228446189339915094527360 92923426425002851172634311446770729875573243622981632.000000,49038509684686202755808411764574575003743211375155249005916427827780247417991687082747214451 073341675744581253991867335918252416362555908299070786942125737694751726823604090062182039519355613866611467434357822207669472484839486934106348907556279 40839424.000000
101 0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000,0.000000
Checking the return value from fscanf() against the expected value, not against EOF is a good idea. #BLUEPIXY #Peter. This will identify/solve most of OP's problems.
The data file has keywords in it, they needed to be scanned too. #user3386109
Suggest direct code to read the entire record with one fscanf().
struct kk {
int time;
int switchn[4];
double potentiometer, temperature, light;
};
int data_kk_read(FILE *inf, struct kk *data) {
int cnt = fscanf(inf,
" time: %d ms switch0: %d switch1: %d switch2: %d"
" switch3: %d potentiometer: %lf temperature: %lf light: %lf"
" --------------------------- ",
&data->time,&data->switchn[0],&data->switchn[1], &data->switchn[2],
&data->switchn[3], &data->potentiometer, &data->temperature, &data->light);
return cnt;
}
int data_kk_write(FILE *outf, unsigned n, const struct kk *data) {
int cnt = fprintf(outf,
"%3u %d, %d, %d, %d, %d, %.2lf, %.2lf, %.2lf\n", n,
data->time, data->switchn[0], data->switchn[1], data->switchn[2],
data->switchn[3], data->potentiometer, data->temperature, data->light);
return cnt;
}
int main(void) {
FILE *inf = fopen("data.txt", "r");
assert(inf);
unsigned line = 0;
struct kk data;
int cnt;
while ((cnt = data_kk_read(inf, &data)) == 8) {
data_kk_write(stdout, ++line, &data);
}
fclose(inf);
if (cnt != EOF) puts("Unexpected scanning problem");
return 0;
}
Output
1 40, 1, 1, 1, 1, 0.00, 0.66, 0.23
2 80, 1, 1, 1, 1, 0.00, 0.66, 0.23
3 120, 1, 1, 1, 1, 0.00, 0.66, 0.23

Post Order print without recursion

This is what i have so far. I really don't understand where i went wrong. It needs to print after it has visited the left most node and then right then print.
void printPostOrderIterative(BSTNode *root)
{
BSTNode *cur;
Stack s;
s.top = NULL;
Stack output;
output.top = NULL;
if (!root) {
return;
}
push(&s, root);
while (isEmpty(&s) != 1 ) {
cur = s.top;
push(&output,cur);
pop(&s);
if (cur->left){
push(&s, cur->left);
}
if (cur->right){
push(&s, cur->right);
}
}
while (isEmpty(&output) != 1) {
printf("%d", output.top);
pop(&output);
}
}
Currently, the code just keeps looping in the first while loop.
Here is some working code. I had to implement an approximation to your stack code, and the BST code, but I made only very simple changes to your function. There are arguments that I should not have had to do the creation: Stack Overflow encourages you to create an MCVE (How to create a Minimal, Complete, and Verifiable Example?)
SSCCE (Short, Self-Contained, Correct Example) — two names and links for the same basic idea.
Without any major algorithmic tweaks, your code (a) completes and (b) produces the same answer as a recursive post-order print function (on one sample data set).
static void printPostOrderIterative(BSTNode *root)
{
if (!root) // Moved to avoid stack initialization before returning
return; // …ditto…
Stack s;
Stack output;
init(&s); // Different initialization
init(&output); // Different initialization
push(&s, root);
while (isEmpty(&s) != 1)
{
BSTNode *cur = top(&s); // Different code
push(&output, cur);
pop(&s);
if (cur->left)
push(&s, cur->left);
if (cur->right)
push(&s, cur->right);
}
while (isEmpty(&output) != 1)
{
BSTNode *c = top(&output); // Different code
printf(" %d", c->data); // Added space
pop(&output);
}
putchar('\n'); // Extra code
clean(&s); // Extra code
clean(&output); // Extra code
}
Thus the problem is probably not in the code you show — it is more likely in the code you don't show. My best guess is that the stack implementation is slightly faulty, but since you don't show it, it is hard to be sure.
Full code
#include <assert.h>
#include <errno.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct BSTNode BSTNode;
struct BSTNode
{
int data;
BSTNode *left;
BSTNode *right;
};
typedef struct Stack
{
size_t size;
size_t top;
BSTNode **stack;
} Stack;
static void err_syserr(const char *fmt, ...)
{
int errnum = errno;
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
if (errnum != 0)
fprintf(stderr, "(%d: %s)\n", errnum, strerror(errnum));
exit(1);
}
static void push(Stack *sp, BSTNode *np)
{
assert(sp != 0 && np != 0);
if (sp->top == sp->size)
{
size_t n_size = (sp->size + 2) * 2;
void *n_data = realloc(sp->stack, n_size * sizeof(*sp->stack));
if (n_data == 0)
err_syserr("Out of memory (%zu bytes requested)\n",
n_size * sizeof(*sp->stack));
sp->stack = n_data;
sp->size = n_size;
}
sp->stack[sp->top++] = np;
}
static bool isEmpty(Stack *sp)
{
return sp->top == 0;
}
static void pop(Stack *sp)
{
if (!isEmpty(sp))
sp->top--;
}
static void init(Stack *sp)
{
sp->top = 0;
sp->size = 0;
sp->stack = 0;
}
static BSTNode *top(Stack *sp)
{
if (sp->top == 0)
return 0;
return sp->stack[sp->top - 1];
}
static void clean(Stack *sp)
{
while (sp->top > 0)
free(sp->stack[--sp->top]);
free(sp->stack);
init(sp);
}
static BSTNode *new_node(int data)
{
BSTNode *np = malloc(sizeof(*np));
if (np == 0)
err_syserr("Out of memory (%zu bytes requested)\n", sizeof(*np));
np->data = data;
np->left = 0;
np->right = 0;
return np;
}
static void printPostOrderIterative(BSTNode *root)
{
if (!root)
return;
Stack s;
Stack output;
init(&s); // Different initialization
init(&output); // Different initialization
push(&s, root);
while (isEmpty(&s) != 1)
{
BSTNode *cur = top(&s); // Different code
push(&output, cur);
pop(&s);
if (cur->left)
push(&s, cur->left);
if (cur->right)
push(&s, cur->right);
}
while (isEmpty(&output) != 1)
{
BSTNode *c = top(&output);
printf(" %d", c->data);
pop(&output);
}
putchar('\n'); // Extra code
clean(&s); // Extra code
clean(&output); // Extra code
}
static void printPostOrderRecursive(BSTNode *root)
{
if (root != 0)
{
printPostOrderRecursive(root->left);
printPostOrderRecursive(root->right);
printf(" %d", root->data);
}
}
static void printInOrderRecursive(BSTNode *root)
{
if (root != 0)
{
printInOrderRecursive(root->left);
printf(" %d", root->data);
printInOrderRecursive(root->right);
}
}
static BSTNode *bst_add(BSTNode *root, int data)
{
if (root == 0)
root = new_node(data);
else if (root->data > data)
root->left = bst_add(root->left, data);
else
root->right = bst_add(root->right, data);
return root;
}
static void bst_destroy(BSTNode *root)
{
if (root != 0)
{
bst_destroy(root->left);
bst_destroy(root->right);
free(root);
}
}
int main(void)
{
int data[] =
{
71, 57, 4, 31, 47, 65, 69, 65, 98, 81,
54, 58, 17, 37, 48, 64, 64, 93, 40, 22,
45, 62, 99, 47, 18, 86, 67, 99, 68, 27,
};
enum { NUM_DATA = sizeof(data) / sizeof(data[0]) };
BSTNode *root = 0;
for (int i = 0; i < NUM_DATA; i++)
{
root = bst_add(root, data[i]);
printInOrderRecursive(root);
putchar('\n');
}
printPostOrderRecursive(root);
putchar('\n');
printPostOrderIterative(root);
bst_destroy(root);
return 0;
}
Sample output
71
57 71
4 57 71
4 31 57 71
4 31 47 57 71
4 31 47 57 65 71
4 31 47 57 65 69 71
4 31 47 57 65 65 69 71
4 31 47 57 65 65 69 71 98
4 31 47 57 65 65 69 71 81 98
4 31 47 54 57 65 65 69 71 81 98
4 31 47 54 57 58 65 65 69 71 81 98
4 17 31 47 54 57 58 65 65 69 71 81 98
4 17 31 37 47 54 57 58 65 65 69 71 81 98
4 17 31 37 47 48 54 57 58 65 65 69 71 81 98
4 17 31 37 47 48 54 57 58 64 65 65 69 71 81 98
4 17 31 37 47 48 54 57 58 64 64 65 65 69 71 81 98
4 17 31 37 47 48 54 57 58 64 64 65 65 69 71 81 93 98
4 17 31 37 40 47 48 54 57 58 64 64 65 65 69 71 81 93 98
4 17 22 31 37 40 47 48 54 57 58 64 64 65 65 69 71 81 93 98
4 17 22 31 37 40 45 47 48 54 57 58 64 64 65 65 69 71 81 93 98
4 17 22 31 37 40 45 47 48 54 57 58 62 64 64 65 65 69 71 81 93 98
4 17 22 31 37 40 45 47 48 54 57 58 62 64 64 65 65 69 71 81 93 98 99
4 17 22 31 37 40 45 47 47 48 54 57 58 62 64 64 65 65 69 71 81 93 98 99
4 17 18 22 31 37 40 45 47 47 48 54 57 58 62 64 64 65 65 69 71 81 93 98 99
4 17 18 22 31 37 40 45 47 47 48 54 57 58 62 64 64 65 65 69 71 81 86 93 98 99
4 17 18 22 31 37 40 45 47 47 48 54 57 58 62 64 64 65 65 67 69 71 81 86 93 98 99
4 17 18 22 31 37 40 45 47 47 48 54 57 58 62 64 64 65 65 67 69 71 81 86 93 98 99 99
4 17 18 22 31 37 40 45 47 47 48 54 57 58 62 64 64 65 65 67 68 69 71 81 86 93 98 99 99
4 17 18 22 27 31 37 40 45 47 47 48 54 57 58 62 64 64 65 65 67 68 69 71 81 86 93 98 99 99
18 27 22 17 45 40 37 47 48 54 47 31 4 62 64 64 58 68 67 65 69 65 57 86 93 81 99 99 98 71
18 27 22 17 45 40 37 47 48 54 47 31 4 62 64 64 58 68 67 65 69 65 57 86 93 81 99 99 98 71
Discussion
Since you used interleaved declarations and statement, you're using at least C99 so I've used <stdbool.h> and bool type. This code compiles cleanly, at least when compiled with the options (Mac OS X 10.11.4, GCC 5.3.0):
$ gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
> -Wold-style-definition -Werror nr-post.c -o nr-post
$
The code runs cleanly under valgrind (3.12.0-SVN).
The first lines of output are printed in-order as the tree is built up (from 30 integers from the range 0..99 generated at random). This allows me to see that the tree is built correctly from the ground up. The last two lines of output are first from printPostOrderRecursive(), a simple recursive implementation of post-order printing, and then from (my mild adaptation of your) printPostOrderIterative().
Without your stack implementation available, I have to guess that you have a problem somewhere in there. With a straight-forward implementation of a stack as shown (where the top is an index into the array of node pointers), your code is fine. We can't tell whether you have compilation warnings you're ignoring.
Hmmm, reviewing my code, I see it doesn't check that top() returns a non-null pointer. It's tempting to add an assertion, and a run-time error rather than returning null. There are plenty of other assertions that could be added — non-null stack pointers passed to the stack functions, in particular.

Partial Threaded Sorting in C

I'm trying to do a partial sort with a threads,
my current output it
27 12 21 48 15 28 82 69 35 91
13 82 33 35 46 5 35 28 87 95
0 10 20 22 23 30 52 80 86 96
3 8 42 53 67 70 70 71 75 79
5 8 8 18 41 43 70 79 86 88
10 51 56 60 65 84 87 91 94 99
23 25 38 39 40 44 51 56 69 75
20 21 25 29 29 38 66 71 73 96
33 50 9 6 13 27 97 21 70 22
3 4 6 6 7 15 34 59 63 70
As you can see I am getting it partially sorted I want my output to be this (no merging at the end)
12 15 21 27 28 35 48 69 82 91
5 13 28 33 35 35 46 82 87 95
0 10 20 22 23 30 52 80 86 96
3 8 42 53 67 70 70 71 75 79
5 8 8 18 41 43 70 79 86 88
10 51 56 60 65 84 87 91 94 99
23 25 38 39 40 44 51 56 69 75
20 21 25 29 29 38 66 71 73 96
6 9 13 21 22 27 33 50 70 97
3 4 6 6 7 15 34 59 63 70
I can get the right output if instead of using a struct I use &array[i] and manually input the length
This is the code I have so far:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <pthread.h>
int cmpfunc(const void *a, const void *b) {
return (*(int*)a - *(int*)b);
}
struct values {
int *arrayptr;
int length;
};
void *thread_fn(void *a) {
struct values *start = a;
qsort(start->arrayptr, start->length, sizeof(int), cmpfunc);
return (void*)a;
}
int main(int argc, const char *argv[]) {
FILE *fp = fopen(argv[3], "r");
FILE *fp1 = fopen("numS1.dat", "w+");
//amount of threads
int threadAmount = atoi(argv[1]);
//size of input
int numberAmount = atoi(argv[2]);
//multidimensional array
int array[threadAmount][numberAmount / threadAmount];
for (int i = 0; i < threadAmount; i++)
for (int j = 0; j < numberAmount / threadAmount; j++)
fscanf(fp, "%d", &array[i][j]);
pthread_t threadid[threadAmount];
for (int i = 0; i < threadAmount; ++i) {
struct values a = { array[i], numberAmount / threadAmount };
pthread_create(&threadid[i], NULL, thread_fn, &a);
}
for (int i = 0; i < threadAmount; ++i)
pthread_join(threadid[i], NULL);
for (int i = 0; i < threadAmount; i++) {
if (i != 0)
fprintf(fp1, "\n");
for (int j = 0; j < numberAmount / threadAmount; j++)
fprintf(fp1 ,"%d ", array[i][j]);
}
return 0;
}
Do you know where I am going wrong?
I think its the struct but everything I see online does what I'm doing.
You are passing a pointer to automatic storage to newly created threads: the struct values object becomes invalid as soon as the calling scope is exited, thus it cannot be reliably accessed by the new thread. You should allocate the struct values and pass the pointer to the allocated object as a parameter to pthread_create:
for (int i = 0; i < threadAmount; ++i) {
struct values *a = malloc(sizeof(*a));
a->arrayptr = array[i];
a->length = numberAmount / threadAmount;
pthread_create(&threadid[i], NULL, thread_fn, a);
}
The structure can be freed by the thread function before exiting.
Notes:
the way you split the array into chunks only works if the length is a multiple of the number of threads.
the comparison function does not work for large int values, you should use this instead:
int cmpfunc(const void *a, const void *b) {
return (*(int*)b < *(int*)a) - (*(int*)a < *(int*)b);
}

Resources