I'm trying to make a multi-threaded prime numbers counter program. I've added the critical codes for the understanding (the parseargs function works great in another program and feels unnecessary and I don't want to overload you with code).
Long story short, the program compile and work well with small numbers (up to 1000 max val and 8 threads), but when I'm trying to go with bigger numbers I keep getting a lot of errors like:
segmentation fault: core dumped, Floating point exception, realloc(): invalid next size.
What's wrong with the code? I know that I should use fewer global variables but I'm trying to make it work and then I will make cleaner and better.
And the only place that I'm using realloc is inside of isprime; that works great in my other programs. What's the problem there?
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/mman.h>
void parseargs(char *argv[], int argc, int *lval, int *uval, int *nval, int *tval);
int isprime(int n);
void setFlags();
pthread_mutex_t num_lock;
pthread_mutex_t count_lock;
char *flagarr = NULL;
int num;
int lval = 1;//min value
int uval = 100;//max value
int count = 0;//primes counter
int main (int argc, char **argv)
{
int nval = 10;// how much numbers to print
int tval = 4;// threads number
num = lval;
if (pthread_mutex_init(&num_lock, NULL) != 0) {
printf("\n mutex init has failed\n");
return 1;
}
if (pthread_mutex_init(&count_lock, NULL) != 0) {
printf("\n mutex init has failed\n");
return 1;
}
// Parse arguments
parseargs(argv, argc, &lval, &uval, &nval, &tval);// works 100% (change the defult starting vals)
if (uval < lval)
{
fprintf(stderr, "Upper bound should not be smaller then lower bound\n");
exit(1);
}
if (lval < 2)
{
lval = 2;
uval = (uval > 1) ? uval : 1;
}
if (tval<1)
tval=4;
// Allocate flags
flagarr= (char *)malloc(sizeof(char) * (uval-lval+1));
if (flagarr == NULL)
exit(1);
//Allocate threads
pthread_t* t = (pthread_t *)malloc(sizeof(pthread_t)*tval);
if (t == NULL)
exit(1);
//start threads
for(int i =0; i<tval ; i++){
printf("%d\n",i);
pthread_create(&t[i],NULL,(void*)setFlags,NULL);
}
for(int i =0; i<tval ; i++)
pthread_join(t[i],NULL);
// Print results
nval=count;
printf("Found %d primes from %d to %d%c", count, lval,uval , count ? ' ' : '.');
if(count && nval>0)
printf("and printing the first %d of them:\n",nval);
else
printf("\n");
for (num = lval; (num <= uval) && (nval) ; num++)
if (flagarr[num - lval])
{
nval--;
count--;
printf("%d%c", num, (count && nval) ? ',' : '\n');
}
free(flagarr);
free(t);
return 0;
}
void setFlags()
{
int myNum;
for (; num <= uval;)
{
pthread_mutex_lock(&num_lock);
myNum=num;
num++;
pthread_mutex_unlock(&num_lock);
if (isprime(myNum))
{
flagarr[myNum - lval] = 1;
pthread_mutex_lock(&count_lock);
count ++;
pthread_mutex_unlock(&count_lock);
} else {
flagarr[myNum - lval] = 0;
}
}
}
int isprime(int n)
{
static int *primes = NULL; // NOTE: static !
static int size = 0; // NOTE: static !
static int maxprime; // NOTE: static !
int root;
int i;
// Init primes array (executed on first call)
pthread_mutex_lock(&first_lock);
if (primes == NULL)
{
primes = (int *)malloc(2*sizeof(int));
if (primes == NULL)
exit(1);
size = 2;
primes[0] = 2;
primes[1] = 3;
maxprime = 3;
}
pthread_mutex_unlock(&first_lock);
root = (int)(sqrt(n));
// Update primes array, if needed
while (root > maxprime)
for (i = maxprime + 2 ; ; i+=2)
if (isprime(i))
{
pthread_mutex_lock(&primeFunc_lock);
size++;
primes = (int *)realloc(primes, size * sizeof(int));
if (primes == NULL)
exit(1);
primes[size-1] = i;
maxprime = i;
pthread_mutex_unlock(&primeFunc_lock);
break;
}
// Check 'special' cases
if (n <= 0)
return -1;
if (n == 1)
return 0;
// Check prime
for (i = 0 ; ((i < size) && (root >= primes[i])) ; i++)
if ((n % primes[i]) == 0)
return 0;
return 1;
}
I know that I should use fewer global variables but I'm trying to make it work and then I will make cleaner and better.
For multithreaded programs this approach doesn't work -- you can't write a buggy program first, and make it pretty and bug-free later -- you have to get it bug-free first.
Also, global and static variables and threads generally don't mix.
Now, as others have noted, you access static variables in isprime() without any locks. Think about what would happen when thread T1 executes this code:
for (i = 0 ; ((i < size) && (root >= primes[i])) ; i++)
if ((n % primes[i]) == 0)
and another thread T2 executes this statement at the same time:
primes = (int *)realloc(primes, size * sizeof(int));
Since primes is not an atomic variable, the compiler will (likely) load the value of primes into some register, and continue using that value through the entire loop in T1. The loop will be totally oblivious to the fact that primes may have already been free()d and realloc()ed in T2, and now points to entirely different memory block. T1 will continue reading the old (now dangling) memory.
Similar problems exist throughout your isprimes() function, and easily explain your observed crashes.
If you are on a Linux system, Thread sanitizer (and Address sanitizer) are your friends.
Related
I have an assignment in C Language; the requirement is that I am given number of students, everyone has 2 grades midterm grade and final grade my task is to calculate the number of students who passed. But I will use forking; we will fork Teaching Assistants to separately choose whether a student should pass or not and the number of Teaching Assistants will be passed on terminal.
Everything is fine. I wrote the code, but I noticed something very weird, I got a segmentation fault which is so weird because I am sure I am not accessing wrong memory. I tried to print something (line 53) and I found that this line is printed 4 times actually, which is equal to number of children + parent, although this line above the fork(). My code creates more than one process (TA) and every TA takes a partition and calculate number of passed students and exit with this code and on parent I make for loop and wait until any child dies so I print its exit code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>
void main(int argc, char **argv)
{
int Number_of_TAs = atoi(argv[1]);
int leastgrade = atoi(argv[2]);
int size_of_array = 0;
int flag = 0;
int last_visited = 0;
int ind = 0;
FILE* ptr;
char ch;
// Opening file in reading mode
ptr = fopen("students.txt", "r");
if (NULL == ptr) {
printf("file can't be opened \n");
}
do {
ch = fgetc(ptr);
size_of_array = 2 * ((int)ch - 48);
break;
} while (ch != EOF);
fclose(ptr);
int arr_of_grades[size_of_array];
int arr_of_grades2[size_of_array/2];
FILE *myFile;
myFile = fopen("students.txt", "r");
int *dummy;
fscanf(myFile, "%d", &dummy);
for (int i = 0; i < size_of_array; i++)
fscanf(myFile, "%d", &arr_of_grades[i]);
int index2 = 0;
printf("%d", size_of_array);
printf(" ");
for (int i = 0; i< size_of_array; i=i+2)
{
arr_of_grades2[index2] = arr_of_grades[i] + arr_of_grades[i+1];
index2 = index2 + 1;
}
fclose(myFile);
int pid, stat_loc;
int passed_students = 0;
int partion = size_of_array / (2 * Number_of_TAs );
for (int i=0; i< Number_of_TAs; i++)
{
pid = fork();
ind = ind + partion;
}
if (pid == 0)
{
for (int i = ind; i< ind + partion; i++)
{
if (arr_of_grades2[i]>=leastgrade )
passed_students = passed_students + 1;
}
exit(passed_students);
}
else
{
int sid;
for (int i = 0; i<Number_of_TAs; i++)
{
sid = wait(&stat_loc);
if(!(stat_loc & 0x00FF))
printf(stat_loc>>8);
printf(" ");
}
}
return 0;
}
I am a newbie in C so I didn't try many things
The segmentation fault issue may happen at any array access with the wrong index.
In your case, it may happen at the first 2 lines:
int Number_of_TAs = atoi(argv[1]);
int leastgrade = atoi(argv[2]);
if you execute the program without the 2 parameters.
Another issue of your program is that you should move the if-else statement where you check the pid inside the for loop where you create the processes with the fork() otherwise it creates more processes than expected.
I am trying to solve a question on codechef. This code is running fine as far as logic is considered, but I am having trouble with giving large inputs.
For example, if I give input of 13 or more digits then it does not run in vscode, and if the input is 22 digits or more then it does not run in devc++.
#include <stdio.h>
#include <math.h>
#include<string.h>
int main() {
int t, l, i, flag = 0;
char ch = ' ';
scanf("%d", &t);
char d[t][100000];
int out[t];
for(i = 0; i < t; i++) {
scanf("%s", &d[t]);
size_t len = strlen(d[t]);
printf("\n%d", len);
char ch = d[t][0];
for (size_t j = 0; j < len; j++) {
if ((ch != d[t][j])) {
flag++;
}
}
if (flag >= 2 && flag != (len-1))
out[i]=0;
else
out[i]=1;
flag = 0;
}
for(i = 0; i < t; i++) {
if (out[i] == 1)
printf("Yes\n");
else
printf("No\n");
}
return 0;
}
TEST RUN 1:-
1
11110111111
11
Yes
TEST RUN 2:-
1
111101111111
0
Why doesn't it handle larger inputs?
When you start writing from d[t], you are out of the bounds of the array, meaning that you might be overwriting other parts of your program. You should instead write to d[i].
Also this array is now on the stack, but the stack only has a very limited size, so there is a high risk you might go over that size, which is called a stack overflow. On windows the stack size is I think 1MB, so if t was bigger than 10 you would already exceed that. So you should allocate on the heap instead.
This should work, but I did not test it:
int t = 0;
scanf("%d", &t);
char **d = (char **)malloc(t * sizeof(char *));
for (int i = 0; i < t; i++){
d[i] = (char *)malloc(STR_SIZE * sizeof(char));
scanf("%s", d[i]);
}
I want to store a group of arrays containing 2 numbers in an array. But I only want 2 numbers to be stored when 5 followed by a comma and another number is entered. Essentially, what I want my program to do is read from this array of arrays and perform tasks accordingly. So if the user enters 2, I want to store (2,0) in one space of my array and move on to ask my user for the second number. But if the user types 5,10 I want the program to store (5,10) in that same array. Then my program could filter which array has only one value and which has 2 and do different tasks accordingly. My assignment requires us to not ask 2 numbers for each array which would have made it easier.
This is what I have so far and I know I'm wrong I just don't know where to go from here:
int main(void)
{
int size = 0;
int input;
int factor;
int mdArrays[100][2];
for (size_t i = 0; i < 100; i++)
{
size = i;
scanf("%d,%d", &input, &factor);
if (input != 5 && input != 9)
{
factor = 0;
for (size_t j =0 ; j< 2; j++)
{
mdArrays[i] = input;
mdArrays[j] = factor;
}
}
else if (input == 9)
{
break;
}
else
{
for(int j = 0; j< 2; j++)
{
mdArrays[i] = input;
mdArrays[j] = factor;
}
}
}
for (size_t i =0; i < size; i++)
{
for(size_t j = 0; j < 2; j++)
{
printf("%d,%d", mdArrays[i[j]]);
}
}
}
There were a few issues.
size is one too short (it should be i + 1).
It may be possible to handle 5 vs 5,23 using scanf. But, I prefer to use fgets and strtol and check the delimiter (e.g. whether it's , or not).
The if/else ladder logic can be simplified if we make the first test against input == 9 to stop the loop.
According to your code, you want to force a factor of zero if input != 5. That doesn't make much sense to me, but I've kept that logic [for now].
That may not be what you want/need, but it was my best interpretation of your code. The main purpose is to differentiate how many numbers are on a given line. So, adjust the rest as needed.
I think the way you're storing/displaying the array is incorrect. I believe you want to store input into mdArrays[i][0] and factor into mdArrays[i][1]. Using j makes no sense to me.
As I mentioned [in my top comments], the printf in the final loop is invalid.
Note that the code is cleaner if we don't hardwire the dimensions with a literal 100 in multiple places (e.g. once in the myArrays declaration and again in the outer for loop). Better to use (e.g.) #define MAXCOUNT 100 and replace 100 elsewhere with MAXCOUNT (see below).
I created three versions. One that is annotated with original and fixed code. Another that removes the original code. And, a third that organizes the data using a struct.
Here's the refactored code. I've bracketed your/old code [vs. my/new code] with:
#if 0
// old code
#else
// new code
#endif
I added a debug printf. Anyway, here's the code with some annotations:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(void)
{
int size = 0;
int input;
int factor;
int mdArrays[100][2];
for (size_t i = 0; i < 100; i++) {
#if 0
size = i;
scanf("%d,%d",&input,&factor);
#else
// get line
char buf[100];
char *cp = fgets(buf,sizeof(buf),stdin);
if (cp == NULL)
break;
// strip newline -- only needed for debug print
cp = strchr(buf,'\n');
if (cp != NULL)
*cp = 0;
// decode first number
input = strtol(buf,&cp,10);
// decode second number if it exists -- otherwise, use a sentinel
if (*cp == ',')
factor = strtol(cp + 1,&cp,10);
else
factor = -1;
printf("DEBUG: buf='%s' input=%d factor=%d\n",buf,input,factor);
#endif
// stop input if we see the end marker
if (input == 9)
break;
// remember number of array elements
size = i + 1;
// only use a non-zero factor if input is _not_ 5
if (input != 5) {
factor = 0;
#if 0
for (size_t j = 0; j < 2; j++) {
mdArrays[i] = input;
mdArrays[j] = factor;
}
continue;
#endif
}
#if 0
for (int j = 0; j < 2; j++) {
mdArrays[i] = input;
mdArrays[j] = factor;
}
#else
mdArrays[i][0] = input;
mdArrays[i][1] = factor;
#endif
}
for (size_t i = 0; i < size; i++) {
#if 0
for (size_t j = 0; j < 2; j++) {
printf("%d,%d",mdArrays[i[j]]);
}
#else
printf("%d,%d\n",mdArrays[i][0],mdArrays[i][1]);
#endif
}
return 0;
}
Here's the sample input I used to test:
5,3
7,6
8,9
5,37
5
9,23
Here's the program output:
DEBUG: buf='5,3' input=5 factor=3
DEBUG: buf='7,6' input=7 factor=6
DEBUG: buf='8,9' input=8 factor=9
DEBUG: buf='5,37' input=5 factor=37
DEBUG: buf='5' input=5 factor=-1
DEBUG: buf='9,23' input=9 factor=23
5,3
7,0
8,0
5,37
5,-1
Here's a slightly cleaned up version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXCOUNT 100
int
main(void)
{
int size = 0;
int input;
int factor;
int mdArrays[MAXCOUNT][2];
for (size_t i = 0; i < MAXCOUNT; i++) {
// get line
char buf[100];
char *cp = fgets(buf,sizeof(buf),stdin);
if (cp == NULL)
break;
// strip newline -- only needed for debug print
#ifdef DEBUG
cp = strchr(buf,'\n');
if (cp != NULL)
*cp = 0;
#endif
// decode first number
input = strtol(buf,&cp,10);
// decode second number if it exists -- otherwise, use a sentinel
if (*cp == ',')
factor = strtol(cp + 1,&cp,10);
else
factor = -1;
#ifdef DEBUG
printf("DEBUG: buf='%s' input=%d factor=%d\n",buf,input,factor);
#endif
// stop input if we see the end marker
if (input == 9)
break;
// remember number of array elements
size = i + 1;
// only use a non-zero factor if input is _not_ 5
if (input != 5)
factor = 0;
mdArrays[i][0] = input;
mdArrays[i][1] = factor;
}
for (size_t i = 0; i < size; i++)
printf("%d,%d\n",mdArrays[i][0],mdArrays[i][1]);
return 0;
}
You might benefit from using a struct [YMMV], so here's a version that keeps things organized that way:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXCOUNT 100
typedef struct {
int input;
int factor;
} data_t;
int
main(void)
{
int size = 0;
data_t mdArrays[MAXCOUNT];
data_t *data;
for (size_t i = 0; i < MAXCOUNT; i++) {
// get line
char buf[100];
char *cp = fgets(buf,sizeof(buf),stdin);
if (cp == NULL)
break;
// strip newline -- only needed for debug print
#ifdef DEBUG
cp = strchr(buf,'\n');
if (cp != NULL)
*cp = 0;
#endif
data = &mdArrays[i];
// decode first number
data->input = strtol(buf,&cp,10);
// decode second number if it exists -- otherwise, use a sentinel
if (*cp == ',')
data->factor = strtol(cp + 1,&cp,10);
else
data->factor = -1;
#ifdef DEBUG
printf("DEBUG: buf='%s' input=%d factor=%d\n",buf,input,factor);
#endif
// stop input if we see the end marker
if (data->input == 9)
break;
// remember number of array elements
size = i + 1;
// only use a non-zero factor if input is _not_ 5
if (data->input != 5)
data->factor = 0;
}
for (size_t i = 0; i < size; i++) {
data = &mdArrays[i];
printf("%d,%d\n",data->input,data->factor);
}
return 0;
}
Read a line of user input with fgets() and then parse it to see if it is one number, two comma separated numbers or something else.
I recommend using `"%n" to detect when and how scanning finished.
int get_numbers(int *input, int *factor) {
char buf[80];
if (fgets(buf, sizeof buf, stdin)) {
int n = 0;
sscanf(buf, "%d %n", input, &n);
if (n > 0 && buf[n] == '\0') return 1;
n = 0;
sscanf(buf, "%d ,%d %n", input, factor, &n);
if (n > 0 && buf[n] == '\0') return 2;
return 0; // Invalid input
}
return EOF; // No input
}
Usage
// scanf("%d,%d", &input, &factor);
switch (get_numbers(&input, &factor)) {
case 2: printf("%d %d\n", input, factor); break;
case 1: printf("%d\n", input); break;
case 0: printf("Invalid input\n"); break;
case EOF: printf("No input\n"); break;
}
I learning C programing and I think I do well but this I have been trying for hours and I don't get what I'm doing wrong.
I made a funtion to print an array and it works fine but just the first time, later on print weird character o don't work, with the gdb see that works fine but when I call printArray a second time the funtion integerToString dosen't works the second time. Honestly I don't know how to fix it, I asking for a few help please ;-; I'm asking anything you comment
The folowing code is a minimum reproducible example but the problem I think is just in the seeArray function and integerToString function
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
//Dependecy
int randomInRange(int lower, int upper){
return (random() % (upper - lower + 1)) + lower;
}
//Dependecy
int countDigits(int num, int * numSize){
*numSize = 0;
do{
(* numSize)++;
num /= 10;
}while(num != 0);
return 0;
}
//Here is where things gets broke!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
int integerToString(int num, char** strNum, int* strNumSize){
countDigits(num, strNumSize);
*strNum = (char *) malloc(sizeof(char) * (*strNumSize));
if(*strNum == 0x0){
fprintf(stderr, "No enough memory for convert interger to string");
exit(EXIT_FAILURE);
}
for(int i = (*strNumSize-1); i > -1; i--){
*( (*strNum) + i ) = num%10 + '0';
num /= 10;
}
return 0;
}
//Dependecy
int initArray(int** array, int size){
if(size<1){
fprintf(stderr, "The array\'s size most be minimun one");
exit(EXIT_FAILURE);
}
*array = (int*) malloc(sizeof(int)*size);
if(*array == NULL){
fprintf(stderr, "Couldn\'t reserve memory for array");
exit(EXIT_FAILURE);
}
for(int i = 0; i < size; i++) *((*array)+i) == 0;
return 0;
}
//Here is where things gets broke!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
int seeArray(int* array, int size, char** arrayPhotography, int* arrayPhotographySize){
int dataSize = 0;
char* data = 0x0;
for(int i = 0; i < size; i++){
integerToString(*(array+i), &data, &dataSize);
*arrayPhotographySize += sizeof(char) * ( 2 + dataSize );
if(*arrayPhotography == 0x0){
*arrayPhotography = (char *) malloc(*arrayPhotographySize);
}else{
*arrayPhotography = (char *) realloc(*arrayPhotography,*arrayPhotographySize);
}
if(*arrayPhotography == 0x0){
fprintf(stderr,"Not enoug memory for array\'s photography");
exit(EXIT_FAILURE);
}
strcat(*arrayPhotography, "[");
strcat(*arrayPhotography, data);
strcat(*arrayPhotography, "]");
free(data);
data = 0x0;
}
free(data);
return 0;
}
//Dependecy
int printArray(int* array, int size){
int arrayPhotographySize = 0;
char* arrayPhotography = 0x0;
if(seeArray(array, size, &arrayPhotography, &arrayPhotographySize)){
fprintf(stderr, "Fuction printArray");
exit(EXIT_FAILURE);
}
printf("Array:%s\n", arrayPhotography);
free(arrayPhotography);
return 0;
}
//Here is where things gets broke!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
int main(int argc, char * argv[]){
srand(time(NULL));
int arraySize = randomInRange(1, 15);
int* array = 0x0;
initArray(&array, arraySize);
for (int i = 0; i < 10; i++){
printArray(array, arraySize);
}
free(array);
}
This are an image of how works randomly (I think so)
It appears that in your initArray function, in the final for loop you write == instead of = to zero-fill the array. On a side note, there exists a function calloc in the <stdlib.h> header which will automatically zero-fill a dynamically allocated array for you, which is handy for avoiding simple mistakes like this.
In your integerToString function, you only malloc enough space to hold the number of digits in the string. This is error-prone code however because most string operations in C (including strcat) require strings to be terminated by a null character. Allocate space for one extra character and then ensure the final character is 0.
Hello I am taking an intro to C-programming class so I am using very basic codes. Here I am simply trying to get a matrix of the commas out of the main string. However when I try running the program it keeps crashing on me and I don't know what is my problem. I was able to use the fgets function correctly so I think that is working fine still.
CD Data.txt File
Eagles, Hotel California, 1976, Rock, 4
The Fratellis, Costello Music, 2006, Garage Rock, 5
Awolnation, Megalithic Symphony, 2011, Indie Rock, 5
Lindsey Stirling, Lindsey Stirling, 2012, Classical Crossover, 5
Arctic Monkeys, AM, 2013, Indie Rock, 4
Program
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define row 1000
#define column 1000
void getCommas(char str[], int commas[])
{
int flag, count, index;
count = 0;
index = 0;
flag = 1;
while(flag = 1)
{
if(str[count] = ',')
{
commas[index] = count;
index = index + 1;
}
count = count + 1;
if(str[count] = '\0')
{
flag = 0;
}
}
}
int main()
{
int i;
char CdInfo[row][column];
int Index[row][column];
FILE *fp;
fp = fopen("CD Data.txt","r");
for(i=0; i<5; i++)
{
fgets(CdInfo[i], sizeof CdInfo, fp);
//printf("%s\n",CdInfo[i]);
}
for (i=0; i<5; i++)
{
getCommas(CdInfo[i], Index[i]);
}
fclose(fp);
return 0;
}
These two variables are too big to be on the stack:
int main()
{
int i;
char CdInfo[row][column]; //<<
int Index[row][column]; //<<
declare them as static or as global variables.
And:
while(flag = 1)
should be
while(flag == 1)
and all
if (str[count] = ...
should be
if(str[count] == ...
You should also think about replacing
while(flag = 1) {
with :
while(flag == 1)
// note:
// the code is not making any use of more than one line of the
// input file at any one time, so
// only the current row actually needs to be defined
// note:
// this code makes no check for max length of each row (1000 char)
// that could/will be a problem when the input line is longer than 1000 character
// to avoid the error of writing an assignment rather than a literal,
// place the literal on the left side,
// then the compiler will notify you of the error
// rather than you having to spend time debugging the code
// trying to find the error
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define row 1000
#define column 1000
//void getCommas(char str[], int commas[])
void getCommas( char * pStr, int * pCommas )
{
//int flag, count, index;
//count = 0;
//index = 0;
//flag = 1;
int flag = 1;
int count = 0;
int index = 0;
//while(flag = 1)
// following while loop could eliminate
// the 'flag' variable and related code by using
// and would be safer because never looking at string termination
// character but once.
// while( '\0' != pStr[count] )
while( 1 == flag )
{
//if(str[count] = ',')
if( ',' == pStr[count] )
{
pCommas[index] = count;
index = index + 1;
}
count = count + 1;
//if(str[count] = '\0')
if( '\0' == pStr[count] )
{ // then found end of string
flag = 0;
}
}
}
char CdInfo[row][column];
int Index[row][column];
int main()
{
int i = 0;
int rowCount = 0;
//char CdInfo[row][column]; // this is a huge item on the stack,
//int Index[row][column]; // this is a huge item on the stack,
//FILE *fp;
FILE *fp = NULL;
fp = fopen("CD Data.txt","r");
// always check the result of calls to io functions
if ( NULL == fp )
{ // then fopen failed
perror( "fopen" );
exit(1);
}
// implied else
// there is no reasonable reason (in the real world)
// to expect the input to be only 5 lines
//for(i=0; i<5; i++)
//{
// fgets(CdInfo[i], sizeof CdInfo, fp);
// //printf("%s\n",CdInfo[i]);
//}
for( i=0; i<row; i++ )
{
// following line checks results of call to I/O function
if( 0 == fgets( CdInfo[i], row, fp ) ) { break; }
// above line exits loop on end of file or I/O error
rowCount++;
}
//for (i=0; i<5; i++)
for( i = 0; i < rowCount; i++ )
{
getCommas(CdInfo[i], Index[i]);
}
fclose(fp);
return 0;
}