Process data from char array - c

I have a little problem,
I have a char array like this:
char buff[256] = { "2 22 3 14 5 8 23 45 2 7 88"};
and what I need to do is:
if 1st number in buff is bigger than 5 I need to sort this numbers ASC
if 1st number in buff is smaller than 5 I need to sort this numbers DESC
in this example the 1st number is 2, so I need to sort this array DESC
I want to create an int array and copy numbers from char buff to int array but I can't figure out how to do this.
Sorting this data in int array will be easy.
I have tried smth like this:
int array[256];
for (int i = 0; i<26; i++)
array[i] = atoi(&buff2[i]);
and the result is not good
array[0]: 2
array[1]: 22
array[2]: 22
array[3]: 2
array[4]: 3
array[5]: 3
array[6]: 14
array[7]: 14
array[8]: 4
array[9]: 5
array[10]: 5
array[11]: 8
array[12]: 8
array[13]: 23
array[14]: 23
array[15]: 3
array[16]: 45
array[17]: 45
array[18]: 5
array[19]: 2
array[20]: 2
array[21]: 7
array[22]: 7
array[23]: 88
array[24]: 88
array[25]: 8

For a 'C' answer, I would use strtol, because it tells you where the parsed number ends in the buffer:
#include <stdio.h>
#include <stdlib.h>
int main() {
char buff[] = "2 22 3 14 5 8 23 45 2 7 88";
char* p=buff;
for(;;) {
char* ep; // end pointer
int n = strtol(p, &ep, 0);
// if ep == p, no parsing took place
if(p != ep) {
// parsing succeeded
printf("%d\n", n);
}
if(!*ep) break; // check if we hit the end of the string
p = ep + 1; // advance to the next character
}
}
Prints:
2
22
3
14
5
8
23
45
2
7
88

For C++, you may want to convert the text to a std::istringstream then treat as an input stream:
const char buff[] = { "2 22 3 14 5 8 23 45 2 7 88"};
const std::string text(buff);
std::vector<int> database;
std::istringstream buf_stream(text);
int value;
while (buf_stream >> value)
{
database.push_back(value);
}
For ascending and descending sorting, you can write comparison functions and pass them to std::sort.

Related

Why is there a segmentation-fault error only with certain input values on pascal's triangle? (C)

I am trying to create a program outputting the pascal's triangle, using C in OnlineGDB and repl.it using a 2x2 array asking how many lines the user wants to print. The main problem is that the program works, but only until printing for 7 rows in onlinegdb, and only 3 rows in repl.it.
There is no error in OnlineGDB, and repl.it says "signal: segmentation fault (core dumped)"
Additionally, I added 3 "PASS" print lines to see where the error occurs, and when reaching the 8th line in onlineGDB it passes all 3 of the for statements filling the array. When reaching the 4th line in repl.it passes all 3 of the for statements filling the array, but both of them doesn't print out the correct numbers. Again, inputted numbers below these values show that all of the code works.
Is there a fix for this, or is it an error with websites handling arrays?
#include <stdio.h>
int main(void){
int intCount;
int intCount1;
int intRows;
int intColumns;
printf("HOW MANY ROWS DO YOU WANT?? ");
scanf("%i", &intRows);
intColumns = intRows;
int intNum[intRows][intColumns];
printf("PASS ");
// FIRST FILL ARRAY WITH 0
for(intCount = 0; intCount <= intRows+1; ++intCount){
for(intCount1 = 0; intCount1 <= intColumns+1; ++intCount1){
intNum[intCount][intCount1] = 0;
}
}
printf("PASS ");
// SET STARTING POINT (1)
intNum[0][0] = 1;
// NOW FILL ARRAY WITH PASCAL TRIANGLE
for(intCount = 0; intCount <= intRows; ++intCount){
for(intCount1 = 0; intCount1 <= intColumns; ++intCount1){
intNum[intCount+1][intCount1+1] = ((intNum[intCount][intCount1+1])+ (intNum[intCount][intCount1]));
}
}
printf("PASS\n");
// NOW PRINT ARRAY
for(intCount = 0; intCount <= intRows; ++intCount){
for(intCount1 = 0; intCount1 <= intColumns; ++intCount1){
// WITHOUT ZEROES:
/*if(intNum[intCount][intCount1] != 0){
printf("%5i",intNum[intCount][intCount1]);
}*/
// WITH ZEROES:
printf("%4i",intNum[intCount][intCount1]);
}
printf("\n");
}
return 0;
}
Logic: In the code above I created a 2 x 2 array with height and width dimensions one larger than the user asks for. I then fill the array with zeroes, and start with a 1 in the top left corner. From there I can use the pascals triangle formula by adding the two numbers above it
I tried changing the counting variables of arrays to make sure everything was correct, but it did not help. I originally coded on onlineGDB but used repl.it to see if there was any further errors, to which there was none. Additionally checked other questions on stack.
Desired Output:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
OnlineGDB Output: (limited to 7 rows in the input)
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
repl.it Output: (limited to 3 rows in the input)
1
1 1
1 2 1
Note: In the output, my code also prints the 0s at the moment and the whole array so that I can visualize it. I am also 100% sure it's the same code uploaded to both
This could be something simple, but I appreciate all the help I can get. I'm more curious why the outputs are different on separate websites with the same code.
Why are you using loops like
for (intCount = 0; intCount <= intRows+1; ++intCount)
{
for (intCount1 = 0; intCount1 <= intColumns+1; ++intCount1)
{
intNum[intCount][intCount1] = 0;
}
}
when you allocated intNum[intRows][intColumns]? You are trampling way out of bounds. That's why your code crashes. That's why you get different behaviours in different systems.
Use:
for (int i = 0; i < intRows; i++)
{
for (int j = 0; j < int columns; j++)
intNum[i][j] = 0;
}
or an equivalent. Note that you use < and not <=; you use the declared limit, not that limit plus one.
Here is some working code, printing without the zeros. Your algorithm for generating the values in Pascal's Triangle was flawed on at least two counts. As before, it trampled way out of bounds of the array, and it also produced two rows with a single 1 in the output (when zeros were not printed). This code avoids those flaws. It also uses i and j as the loop counters — old Fortran programmers die hard.
/* SO 7549-7765 */
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int intRows;
int intColumns;
printf("How many rows do you want? ");
if (scanf("%i", &intRows) != 1)
{
fprintf(stderr, "failed to read an integer\n");
exit(1);
}
if (intRows < 1 || intRows > 64)
{
fprintf(stderr, "value %d is outside the range 1..64\n", intRows);
exit(1);
}
printf("Rows: %d\n", intRows);
intColumns = intRows;
int intNum[intRows][intColumns];
printf("PASS\n");
// First, fill array with zeros
for (int i = 0; i < intRows; i++)
{
for (int j = 0; j < intColumns; j++)
{
intNum[i][j] = 0;
}
}
printf("PASS\n");
// Set starting point (1)
intNum[0][0] = 1;
// Now fill array with Pascal's Triangle
for (int i = 1; i < intRows; i++)
{
intNum[i][0] = intNum[i-1][0];
for (int j = 1; j <= i; j++)
{
intNum[i][j] = intNum[i-1][j-1] + intNum[i-1][j];
}
}
printf("PASS\n");
// Now print array
for (int i = 0; i < intRows; i++)
{
for (int j = 0; j < intColumns; j++)
{
// Without zeros:
if (intNum[i][j] != 0)
printf(" %5d", intNum[i][j]);
// With zeros:
// printf(" %5d", intNum[i][j]);
}
printf("\n");
}
return 0;
}
Note the use of " %5d" in the printing format. That space ensures that the numbers remain separate even if there are 6 or more digits in the values (which first happens with 21 rows requested).
Sample output:
How many rows do you want? 15
Rows: 15
PASS
PASS
PASS
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
1 5 10 10 5 1
1 6 15 20 15 6 1
1 7 21 35 35 21 7 1
1 8 28 56 70 56 28 8 1
1 9 36 84 126 126 84 36 9 1
1 10 45 120 210 252 210 120 45 10 1
1 11 55 165 330 462 462 330 165 55 11 1
1 12 66 220 495 792 924 792 495 220 66 12 1
1 13 78 286 715 1287 1716 1716 1287 715 286 78 13 1
1 14 91 364 1001 2002 3003 3432 3003 2002 1001 364 91 14 1

Finding which values in an array are present at least x times [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I have an array with randomly generated numbers in it, and I need to find and store the numbers that are present at least x times. (I can easily find x, that is not important. It will be a set amount). The array will have around 100-200 elements.
I know I will have to use a loop, but I'm not sure how to structure the body of it. I'm relatively new to C programming, so this may be fairly trivial. Any help is appreciated.
I implemented two solutions, one in C and one in C++.
First solution in C:
It is simple:
Input array of numbers. Either it is inputed from console (when input = 1) or generated automatically by random generator (set constant input = 0 in first lines of main()). Input/generation is done by first loop. If generated automatically/randomly then set constants n (number of elements) and x (minimal allowed count) at first lines of main() function.
Sort them in ascending order by built-in function qsort. I provided compare() function for qsort to compare in ascending order.
Iterate through sorted array. On the way compute number c of consecutive equal numbers. If c >= x then it means we have at least x of consecutive equal numbers, it means this number occured at least x times, hence we output such number as matching our criteria.
Try it online!
#include <stdlib.h>
#include <stdio.h>
static int compare(void const * sa, void const * sb) {
int a = *(int*)sa, b = *(int*)sb;
return a < b ? -1 : a == b ? 0 : 1;
}
int main() {
// "n" - total number of integers, "x" - minimum count to find
// "input" - if 1 then read from console input array, else if 0 generate random
int const n = 50, x = 3, input = 1;
// Example of input: n = 50, x = 3, a = 3 6 17 15 13 15 6 12 9 1 2 7 10 19 3 6 0 6 12 16 11 8 7 9 2 10 2 3 7 15 9 2 2 18 9 7 13 16 11 2 9 13 1 19 4 17 18 4 15 10
// and output for this example: 2: 6 times, 3: 3 times, 6: 4 times, 7: 4 times, 9: 5 times, 10: 3 times, 13: 3 times, 15: 4 times,
if (input) {
printf("Input n and x: ");
scanf("%d %d", &n, &x);
printf("Input array: ");
} else
srand(0); // You may init this with some randomness
int * a = (int*)malloc(sizeof(int) * n); // Allocate memory for empty array
for (int i = 0; i < n; ++i) {
if (input)
scanf("%d", &a[i]);
else {
a[i] = rand() % 20; // Init numbers with random, you may input your numbers
printf("%d ", a[i]); // Print generated numbers
}
}
if (!input)
printf("\n");
qsort(a, n, sizeof(int), compare);
int c = 1;
for (int i = 1; i <= n; ++i) {
if (i == n || a[i] != a[i - 1]) {
if (c >= x)
printf("%d: %d times, ", a[i - 1], c);
c = 1;
} else
++c;
}
free(a);
return 0;
}
Input:
50 3
3 6 17 15 13 15 6 12 9 1 2 7 10 19 3 6 0 6 12 16 11 8 7 9 2 10 2 3 7 15 9 2 2 18 9 7 13 16 11 2 9 13 1 19 4 17 18 4 15 10
Second solution in C++:
Use std::map to count number of occurances of each number, by iterating (in a loop) over input array and incrementing by 1 count of current nummber inside map, then iterate (in a second loop) through this map and output those numbers that occur at least x times.
Also I used std::map specifically to have nice sorted output of numbers, if you don't need sorted order and need more speed then use std::unordered_map instead of std::map exactly same way (also do #include <unordered_map> instead of <map>).
Full code is below:
Try it online!
#include <iostream>
#include <cstdlib>
#include <vector>
#include <map>
using namespace std;
int main() {
size_t const n = 50; // How many numbers
size_t const x = 3; // At least this many times
srand(0); // Use this if only deterministic randoms are needed
vector<int> a(n); // Numbers
for (size_t i = 0; i < a.size(); ++i) {
a[i] = rand() % 20; // Some random numbers
cout << a[i] << " "; // Output our input numbers
}
cout << endl;
map<int, size_t> cnt;
// Count number of occurances
for (auto x: a)
++cnt[x];
// Output numbers that occur at least "x" times
for (auto const & p: cnt)
if (p.second >= x)
cout << p.first << ": " << p.second << " times, ";
return 0;
}
Output:
3 6 17 15 13 15 6 12 9 1 2 7 10 19 3 6 0 6 12 16 11 8 7 9 2 10 2 3 7 15 9 2 2 18 9 7 13 16 11 2 9 13 1 19 4 17 18 4 15 10
2: 6 times, 3: 3 times, 6: 4 times, 7: 4 times, 9: 5 times, 10: 3 times, 13: 3 times, 15: 4 times,

Why am I getting random numbers in my result?

I am trying to 4x4 input in an 5x5 array and get the sum of each lines on the fifth lines.
I'm sure if you read my code below, you'll know what I am trying to talk about.
For example if I type in:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
The expected Result should be:
1 2 3 4 10
5 6 7 8 26
9 10 11 12 42
13 14 15 16 58
28 32 36 40 136
Instead, I am getting a result like:
1 2 3 4 10
5 6 7 8 32792
9 10 11 12 42
13 14 15 16 58
28 32 36 40 -501277720
I thought about why I get these random values, but couldn't find a solution. Why am I getting these values and what can I do to solve it?
#include <stdio.h>
int main ()
{
int gradeArr[5][5];
int i,j;
printf("Input grades:\n");
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
scanf("%d",&gradeArr[i][j]);
gradeArr[i][4] += gradeArr[i][j];
}
}
printf("%d\n", gradeArr[1][4]);
for(i=0;i<4;i++)
{
for(j=0;j<4;j++)
{
gradeArr[4][i] += gradeArr[j][i];
}
gradeArr[4][4] += gradeArr[4][i];
}
printf("Result: \n");
for(i=0;i<5;i++)
{
for(j=0;j<5;j++)
{
printf("%d ",gradeArr[i][j]);
}
printf("\n");
}
return 0;
}
You need to initialize the array.
Try
int gradeArr[5][5] = {0};

stack smashing in string and infinite loop

stack smashing
stuck in loop.
enters an infinite loop randomly.
sometimes during first time sometimes during second.
The code is a mess however. the logic is to split a string into three strings alternatively three times.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char mstr[21];
void split(char str1[21]);
void printx(char strxyz[7]);
void main()
{
int i,j,count=0;
char str[21];
for(i=1;i<=21;i++)
{
str[i-1]=i;
printf("%d\t",str[i-1]);
if(i%7==0)
{
printf("\n");
}
}
while(count<3)
{
split(str);
count++;
}
}
void split(char str1[21])
{
int i,j=0,k,ans,n;
char strx[7],stry[7],strz[7];
printf("\n\n* * * * * split * * * * *\n\n");
for(i=0;i<21;)
{
for(n=0;j<7;n++)
{
strx[j]=str1[i];i=i+1;
stry[j]=str1[i];i=i+1;
strz[j]=str1[i];i=i+1;
j=j+1;
}
}
printf("enter the group\n");
scanf("%d",&ans);
switch(ans)
{
case 1:
strcat(stry,strx);
strcat(stry,strz);
strcpy(mstr,stry);
break;
case 2:
strcat(strx,stry);
strcat(strx,strz);
strcpy(mstr,strx);
break;
case 3:
strcat(strx,strz);
strcat(strx,stry);
strcpy(mstr,strx);
break;
default:
printf("invalid\n");
}
printf("\n mstr values\n");
for(k=0;k<21;k++)
{
printf("%d\t",mstr[k]);
}
}
void printx(char strxyz[7])
{
int i;
printf("\n");
for(i=0;i<7;i++)
{
printf("%d\t",strxyz[i]);
}
}
2nd Output:
student#CSE-LAB3:~/Desktop/fdrive$ cc shuffle.c
student#CSE-LAB3:~/Desktop/fdrive$ ./a.out
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
split * * * * *
enter the group
2
mstr values
1 4 7 10 13 16 19 2 5 8 11 14 17 20 3 6 9 12 15 18 21
split * * * * *
enter the group
2
mstr values
1 4 7 10 13 16 19 2 5 8 11 14 17 20 3 6 2 5 8 11 14
split * * * * *
enter the group
1
Segmentation fault (core dumped)
edited:
the string
str = 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
now we have to split the string into three.
so.
strx = 1 2 3 4 5 6 7
stry = 8 9 10 11 12 13 14
srtrz = 15 16 17 18 19 20 21
now based on the input (1 or 2 or 3 ) merge the string into a single string.
if the input is 1. place the string strx( first sub string ) in the middle. so it becomes
like stry+strx+strz
> output
> 1 4 7 10 13 16 19
> 2 5 8 11 14 17 20
> 3 6 9 12 15 18 21
logic:
Imagine a real life problem.You have 21 cards. You divide it into three stacks of 7 cards. You ask your friend to think of a card from the three stacks.You then ask which stack has the card. The stack that contains the card is placed in the middle of other two stacks and merged without changing the order. Now You have to split the stack of 21 cards into 7 cards stacks . The process is repeated 3 times i.e. he has to choose the stack 3 times.
You have a couple of fundamental problems. The worst is that you are not terminating your strings with '\0' characters. This leads to undefined behavior. Also, you are concatenating, for example, strx to stry. But there is no room in the character array strx[] to hold the additional characters.
You can fix these problems by changing all declarations for arrays of size 21 to 22, e.g., char mstr[22];, and changing all declarations for arrays of size 7 to 8, e.g., char strx[8];. Then you need to be sure to add NUL terminators to the end of each string. One way to accomplish this would be to zero-initialize each of the arrays. Another method is to explicitly add the NUL character, and this is what I have done in the code below.
Then, you need to change the code that combines the strings. This code should copy the first substring into mstr[], and then concatenate the next two substrings:
case 1:
strcpy(mstr,stry);
strcat(mstr,strx);
strcat(mstr,strz);
There is also a significant logic error in the code that splits the strings. The double loop that you have is going out of array bounds. Consider that when i reaches 20, you will have: strz[j]=str1[22];i=22+1;, since i has already been incremented twice. This should be simplified to:
for(i=0, j=0; j < 7; j++, i += 3)
{
strx[j] = str1[i];
stry[j] = str1[i + 1];
strz[j] = str1[i + 2];
}
strx[j] = '\0';
stry[j] = '\0';
strz[j] = '\0';
It sounds like you want to preserve the changes made during each call to split(), so you should remove str[] from main() and instead use the global mstr[] here, since this is the string that you are storing the shuffled results in. It would be much better to remove the global entirely, though, as it is best to only use globals when you have to. Since the split() function distributes the contents of str1 among each of the strings strx, stry, and strz, you can store the combined results back in str1. And since str1 is a pointer to the first element of mstr[], the change is visible in the calling function. To accomplish this, the declaration for mstr[] needs to be moved into main(), and the code to combine strings should look like:
case 1:
strcpy(str1,stry);
strcat(str1,strx);
strcat(str1,strz);
Here is modified code that does more or less what I think you intended. I also added some code to print the resulting array after three calls to split():
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void split(char str1[22]);
void printx(char strxyz[8]);
int main(void)
{
int i,count=0;
char mstr[22];
for(i=0;i<21;i++)
{
mstr[i]=i+1;
printf("%d\t",mstr[i]);
if((i+1)%7==0)
{
printf("\n");
}
}
mstr[i] = '\0';
while(count<3)
{
split(mstr);
count++;
}
printf("\nResults:\n");
for(i=0;i<21;i++)
{
printf("%d\t",mstr[i]);
if((i+1)%7==0)
{
printf("\n");
}
}
}
void split(char str1[22])
{
int i,j,k,ans;
char strx[8],stry[8],strz[8];
printf("\n\n* * * * * split * * * * *\n\n");
for(i=0, j=0;j<7;j++, i+=3)
{
strx[j]=str1[i];
stry[j]=str1[i+1];
strz[j]=str1[i+2];
}
strx[j] = '\0';
stry[j] = '\0';
strz[j] = '\0';
printf("enter the group\n");
scanf("%d",&ans);
switch(ans)
{
case 1:
strcpy(str1,stry);
strcat(str1,strx);
strcat(str1,strz);
break;
case 2:
strcpy(str1,strx);
strcat(str1,stry);
strcat(str1,strz);
break;
case 3:
strcpy(str1,strx);
strcat(str1,strz);
strcat(str1,stry);
break;
default:
printf("invalid\n");
}
printf("\n str1 values\n");
for(k=0;k<21;k++)
{
printf("%d\t",str1[k]);
}
}
void printx(char strxyz[8])
{
int i;
printf("\n");
for(i=0;i<7;i++)
{
printf("%d\t",strxyz[i]);
}
}
In procedure split, you have j<=7 but it should be j<7 or j<=6 to prevent out of bound problem.
What it sounds to me is there may be an uninitialized value or a wrong condition for terminating the loop.
I've spotted a problem, for example in the function,
void split(char str1[21])
{
//i, k and n are later initialized but j is not.
int i,j,k,ans,n;
char strx[7],stry[7],strz[7];
printf("\n\n* * * * * split * * * * *\n\n");
for(i=0;i<21;)
{
//j is not initialized, how do you know compiler will initialize it to 0 for sure?
//j <= 7 should be j < 7
for(n=0;j<=7;n++)
{
strx[j]=str1[i];i=i+1;
stry[j]=str1[i];i=i+1;
strz[j]=str1[i];i=i+1;
j=j+1;
}
}
printf("enter the group\n");
scanf("%d",&ans);
switch(ans)
{
case 1:
strcat(stry,strx);
strcat(stry,strz);
strcpy(mstr,stry);
break;
case 2:
strcat(strx,stry);
strcat(strx,strz);
strcpy(mstr,strx);
break;
case 3:
strcat(strx,strz);
strcat(strx,stry);
strcpy(mstr,strx);
break;
default:
printf("invalid\n");
}
printf("\n mstr values\n");
for(k=0;k<21;k++)
{
printf("%d\t",mstr[k]);
}
}
You declare j without initialization then it is compared against 7 in the for loop where n is incremented. Each time the program is started, they may be initialized to a random value. That's why you might receive undefined behavior. Also j <= 7 should be j < 7

Creating an array with the amount of occurrences from an input file (C)

I've been working tirelessly on this assignment, it's already past due and I cannot for the life of me find a solution. We are behind on lecture and the professor still decided it was okay for us to do homework that we haven't even covered yet.
So this is the main function I've been having problems with. The goal is to read an input file full of integers:
12 15 7 1 19
18 16 15 2 8
5 4 16 7 1
19 4 16 15 3
13 9 12 4 6
9 2 19 13 15
18 20 17 17 4
3 12 2 18 18
10 14 1 14 1
7 10 18 17 18 30
After it reads the file, it's suppose to input the occurrences of each value into an array. So in index 1, there would be however many 1's there are. index 2, there would be however many 2's and so on up until 20. Index 0 will hold the total amount of integers the file contains. The loop continues to scan until it reaches the integer 30.
The length I have set to 999 because the file will never be the same, so it will be kind of random and you'll never know the length. So once it counts through up until 30, I use 'amount' as a counter and then initialize length to equal amount.
For more instruction, this is part of the directions for this function specifically that was given by the professor:
createVArray: This is a void function that takes three parameters: a FILE * and an integer array and an integer indicating the length of the array. Your function should read numbers from the file, one at a time, using the information collected to update the array. The first index of the array will be used to store the total number of votes read while each subsequent index will store the number of votes for that t-shirt logo option. Your function should continue reading the file until the number 30 is encountered.
int array2[999], array[21]; //Global dec
void createVArray(int amount, int length){
int counter, i, j, m;
length = 999;
amount = 0;
for(counter = 1; counter < length; counter++){
fscanf(votesFileptr, "%d", &array[counter]);
if(array[counter] == 30){
for (i = 1, j = 0; i < amount, j < amount; i++, j++){
array2[j] = array[i];
}
break;
}
for(m = 0; m < length; m++){
if (array[m] > 0){
printf("Occurs %d\n", array[m]);
}
}
amount++;
}
length = amount;
array[0] = amount;
for(i = 0; i < 21; i++){
printf("%d\n", array[i]);
}
}
let's start simple
createVArray: This is a void function that takes three parameters: a FILE * and an integer array and an integer indicating the length of the array
void createVArray(FILE* input, int counts[], const int length )
Your function should read numbers from the file, one at a time, using the information collected to update the array
fscanf(input, "%i", &number)
The first index of the array will be used to store the total number of votes read while each subsequent index will store the number of votes for that t-shirt logo option
++counts[0];
++counts[numbers];
Your function should continue reading the file until the number 30 is encountered
if( number == 30 ) return; // or break if you want to
Appart from some loops, additional tests and check you should have the pieces to write your function already
and if you are really desperate : http://pastebin.com/bfNTKVHq
bonus : https://godbolt.org/g/F9GYI0
I'm bored. From the spec you posted, I think your prof wants something like this:
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <stdlib.h>
void createVArray(FILE * fin, int *a, int len){
int i;
assert(len>29);
while(1){
if(fscanf(fin,"%d",&i) !=1){
perror("fscanf error");
exit(1);
}
if(i>=30)
return;
a[0]+=1;
a[i]+=1;
}
}
int main(){
int a[30];
memset(a,0,sizeof(a));
FILE *fin=fopen("test.txt","r");
createVArray(fin,a,30);
for(int i=0; i<30; ++i){
printf("a[%d]=%d\n",i,a[i]);
}
return 0;
}
test.txt:
12 15 7 1 19 18 16 15 2 8 5 4 16 7 1 19 4 16 15 3 13 9 12 4 6 9 2
19 13 15 18 20 17 17 4 3 12 2 18 18 10 14 1 14 1 7 10 18 17 18 30
output:
a[0]=50
a[1]=4
a[2]=3
a[3]=2
a[4]=4
a[5]=1
a[6]=1
a[7]=3
a[8]=1
a[9]=2
a[10]=2
a[11]=0
a[12]=3
a[13]=2
a[14]=2
a[15]=4
a[16]=3
a[17]=3
a[18]=6
a[19]=3
a[20]=1
a[21]=0
a[22]=0
a[23]=0
a[24]=0
a[25]=0
a[26]=0
a[27]=0
a[28]=0
a[29]=0
The problem presents the classic problem of accounting for the number of occurrences within a range. Any time you are presented with this type problem, you will capture the number of occurrences within an array having at least one element for each number in the range. (in your case +1 since you are storing the total votes in the first element.
The next part is to loop over all values reading all values between 1-20 representing votes cast for the corresponding tshirt design. So if you read 13 you need to increment array[13] to note that 1 vote has been recorded for tshirt 13 design. Since you are reading numbers within the range of your array, all you need to do is insure you start with an array initialized to all 0's. When each number is read, you simply increment the value at that index by one. e.g. you read 12 to increment the vote count for tshirt 12 it is simply array[12]++; (or you could do array[12] = array[12] + 1; or array[12] += 1;, they all do the same thing)
During this time you are also keeping a running total of all votes, so every time your read a valid vote from the file, simply do total++; (or total = total + 1; or total += 1;)
Putting it together, you could do something similar to the following, e.g.
#include <stdio.h>
#include <stdlib.h>
#define ARSZ 21 /* array size 0-total, 1-20 shirt votes */
void createVArray (int *a, int n, FILE *fp);
int main (int argc, char **argv) {
int array[ARSZ] = {0};
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
createVArray (array, ARSZ, fp); /* read values from fp */
if (fp != stdin) fclose (fp); /* close file if not stdin */
printf ("\n '%d' votes recorded.\n\n", *array);
for (int i = 1; i < ARSZ; i++)
printf (" tshirt[%2d] : %2d\n", i, array[i]);
return 0;
}
/* read integer values from 'fp' incrementing values in range `array`
* for each value read and returning the total values considered in
* array[0].
*/
void createVArray (int *a, int n, FILE *fp)
{
if (!a || !fp) { /* validate array and FILE stream */
fprintf (stderr, "error: invalid parameter in list.\n");
return;
}
if (!n) { *a = 0; return; } /* validate length */
int tmp = 0, total = 0; /* read into tmp, increment total */
while (fscanf (fp, " %d", &tmp) == 1) { /* validate int read */
if (tmp == 30) break; /* if 30, bail */
if (0 < tmp && tmp <= 20) /* if vote increment */
total++, a[tmp]++; /* total and value at a[tmp] */
}
a[0] = total; /* set first element to hold total votes */
}
Input File
$ cat dat/votes.dat
12 15 7 1 19
18 16 15 2 8
5 4 16 7 1
19 4 16 15 3
13 9 12 4 6
9 2 19 13 15
18 20 17 17 4
3 12 2 18 18
10 14 1 14 1
7 10 18 17 18 30
Example Use/Output
$ ./bin/tshirtvote <dat/votes.dat
'50' votes recorded.
tshirt[ 1] : 4
tshirt[ 2] : 3
tshirt[ 3] : 2
tshirt[ 4] : 4
tshirt[ 5] : 1
tshirt[ 6] : 1
tshirt[ 7] : 3
tshirt[ 8] : 1
tshirt[ 9] : 2
tshirt[10] : 2
tshirt[11] : 0
tshirt[12] : 3
tshirt[13] : 2
tshirt[14] : 2
tshirt[15] : 4
tshirt[16] : 3
tshirt[17] : 3
tshirt[18] : 6
tshirt[19] : 3
tshirt[20] : 1
Easy to see, tshirt design 18 is the big winner with 6 votes out of a total of 50 cast.

Resources