Want to increase dynamic array by use realloc and not successful - c

void main()
{
int *ptr, size, i;
printf("size is:\n");
scanf("%d", &size);
ptr = (int*)malloc(size * sizeof(int));
if (ptr == NULL)
{
printf("Error");
return;
}
ptr = (int*)realloc(ptr, (size + 10) * sizeof(int));
for (i = 0; i <size+10; i++)
{
printf("number %d...\n", i);
scnaf("%d", &ptr[i]);
}
for (i = 0; i < size + 10; i++)
{
printf("%d ", ptr[i]);
}
free(ptr);
}
Want to create a dynamic array, add 10 more places in memory, and absorb the values from the user.
for example, if the user enters 5 for the size, the total size will be size=5+10=15, and if the user then enters:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
the output will be:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
The errors I get are :
Error LNK2019 unresolved external symbol _scnaf referenced in function _main realloc
Error LNK1120 1 unresolved externals realloc
Can you try and help me understand why I'm getting this error?

For starters according to the C Standard the function main without parameters shall be declared like
int main( void )
Secondly there is a typo. You wrote scnaf instead of scanf.
And you have to include headers
#include <stdio.h>
#include <stdlib.h>
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
size_t size;
printf( "size is: " );
scanf( "%zu", &size );
int *ptr = malloc( size * sizeof( int ) );
if ( ptr == NULL )
{
puts( "Error" );
return EXIT_FAILURE;
}
int *tmp = realloc( ptr, ( size + 10 ) * sizeof( int ) );
if ( tmp != NULL )
{
size += 10;
ptr = tmp;
}
for ( size_t i = 0; i < size; i++ )
{
printf("number %zu => ", i );
scanf( "%d", ptr + i );
}
for ( size_t i = 0; i < size; i++ )
{
printf( "%d ", ptr[i] );
}
putchar( '\n' );
free( ptr );
return EXIT_SUCCESS;
}
Its output might look like
size is: 5
number 0 => 1
number 1 => 2
number 2 => 3
number 3 => 4
number 4 => 5
number 5 => 6
number 6 => 7
number 7 => 8
number 8 => 9
number 9 => 10
number 10 => 11
number 11 => 12
number 12 => 13
number 13 => 14
number 14 => 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

There are two problems with your code resulting in errors.
You mistyped scnaf instead of scanf, like #VillageTech noted.
You need to include the appropriate standard library headers: scanf() comes from <stdio.h> and realloc() from <stdlib.h>.
If you fix that, your code compiles (GodBolt.org). It also runs mostly as you would expect.
Note also that "size is:" is a very ambiguous message, and the user will be confused regarding what to do and what to expect later.
There are also other issues with your code, such as failing to check for errors returned from scanf(), or the assumption that realloc() was successful - see #6502's comment.

Ok, I agree, will not smile ;)
This is scanf(), not scnaf() :) :) :)
So:
scanf("%d", &ptr[i]);

Related

Code for Binary search in C not working properly

I can't fix the logical error because I don't know what is wrong in this code. Every input, it shows "element not found". I would really appreciate it if someone can help me in this. Also in this code, I have assumed we'll be taking the size of the array as an odd number, what to do if we decide to take an even number as size?
#include<stdio.h>
int main(){
int size;
printf("Enter the number of elemets(odd number) : ");
scanf("%d",&size);
int arr[size];
printf("Enter the elements in ascending order : ");
for(int i=0;i<size;i++){
scanf("%d",&arr[i]);
}
int element;
int flag=0;
printf("Enter element to be found : ");
scanf("%d",&element);
int low=0;
int high=size-1;
while(low<high){
int mid=(low+high)/2;
if(element<arr[mid]){
high=mid-1;
}
else if(element>arr[mid]){
low=mid+1;
}
else if(element==arr[mid]){
printf("Element %d found at pos %d ",element,mid);
flag=1;
break;
}
}
if(flag==0){
printf("Element not found");
}
return 0;
}
The problem is your while test. You have:
while(low<high) {
...
}
This will fail when low == high if the desired value is at that position. It is easily fixed by changing the test to:
while(low <= high) {
...
}
This is all that's needed to fix it. You don't need to add any special cases to "fix it up". Just make sure your array is in ascending order and it should work.
EDIT: Refer to the better answer by #TomKarzes
My old answer is:
You missed a boundary case of high==low
#include<stdio.h>
int main(){
int size;
printf("Enter the number of elements(odd number) : ");
scanf("%d",&size);
int arr[size];
printf("Enter the elements in ascending order : ");
for(int i=0;i<size;i++){
scanf("%d",&arr[i]);
}
int element;
int flag=0;
printf("Enter element to be found : ");
scanf("%d",&element);
int low=0;
int high=size-1;
while(low<high){
int mid=(low+high)/2;
if(element<arr[mid]){
high=mid-1;
}
else if(element>arr[mid]){
low=mid+1;
}
else if(element==arr[mid]){
printf("Element %d found at pos %d ",element,mid);
flag=1;
break;
}
}
if(low==high && arr[low]==element) //Added 1 extra condition check that you missed
{
printf("Element %d found at pos %d ",element,low);
flag=1;
}
if(flag==0){
printf("Element not found");
}
return 0;
}
For starters for the number of elements of the array you shell use the type size_t. An object of the type int can be small to accommodate the number of elements in an array.
This condition of the loop
int high=size-1;
while(low<high){
//...
is incorrect. For example let's assume that the array has only one element. In this case high will be equal to 0 and hence equal to left due to its initialization
int high=size-1;
So the the loop will not iterate and you will get that the entered number is not found in the array though the first and single element fo the array actually will be equal to the number.
You need change the condition like
while ( !( high < low ) )
//...
This if statement within the else statement
else if(element==arr[mid]){
is redundant. You could just write
else // if(element==arr[mid]){
It would be better if the code that performs the binary search will be placed in a separate function.
Here is a demonstrative program that shows how such a function can be written.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int binary_search( const int a[], size_t n, int value )
{
size_t left = 0, right = n;
int found = 0;
while ( !found && left != right )
{
size_t middle = left + ( right - left ) / 2;
if ( value < a[middle] )
{
right = middle;
}
else if ( a[middle] < value )
{
left = middle + 1;
}
else
{
found = 1;
}
}
return found;
}
int cmp( const void *a, const void *b )
{
int left = *( const int * )a;
int right = *( const int * )b;
return ( right < left ) - ( left < right );
}
int main(void)
{
const size_t N = 15;
srand( ( unsigned int )time( NULL ) );
for ( size_t i = 0; i < N; i++ )
{
size_t n = rand() % N + 1;
int a[n];
for ( size_t j = 0; j < n; j++ ) a[j] = rand() % N;
qsort( a, n, sizeof( int ), cmp );
for ( size_t j = 0; j < n; j++ )
{
printf( "%d ", a[j] );
}
putchar( '\n' );
int value = rand() % N;
printf( "The value %d is %sfound in the array\n",
value, binary_search( a, n, value ) == 1 ? "" : "not " );
}
return 0;
}
Its output might look for example the following way
0 2 2 3 4 5 7 7 8 9 10 12 13 13
The value 5 is found in the array
4 8 12
The value 10 is not found in the array
1 2 6 8 8 8 9 9 9 12 12 13
The value 10 is not found in the array
2 3 5 5 7 7 7 9 10 14
The value 11 is not found in the array
0 1 1 5 6 10 11 13 13 13
The value 7 is not found in the array
0 3 3 3 4 8 8 10 11 12 14 14 14 14
The value 3 is found in the array
0 5 5 10 11 11 12 13 13 14 14
The value 12 is found in the array
3 4 5 7 10 13 14 14 14
The value 14 is found in the array
0 3 3 7
The value 2 is not found in the array
1 6 9
The value 10 is not found in the array
2 2 3 3 4 4 4 5 5 6 8 8 9 13 13
The value 11 is not found in the array
11 11 13
The value 11 is found in the array
0 0 0 1 2 5 5 5 7 7 8 9 12 12 14
The value 6 is not found in the array
8 8 13
The value 1 is not found in the array
2 2 4 4 5 9 9 10 12 12 13 13 14 14
The value 14 is found in the array

To understand %*d and if (( scanf( "%d", &n ) != 1 ) || ( n <= 0 )) in c

I have to print this pattern in c
4 4 4 4 4 4 4
4 3 3 3 3 3 4
4 3 2 2 2 3 4
4 3 2 1 2 3 4
4 3 2 2 2 3 4
4 3 3 3 3 3 4
4 4 4 4 4 4 4
And I found this code associated with it
#include <stdio.h>
#include <limits.h>
#include <stdlib.h>
int main()
{
while ( 1 )
{
printf( "Enter a non-negative number (0 - exit): " );
int n;
if ( ( scanf( "%d", &n ) != 1 ) || ( n <= 0 ) ) break;
if ( INT_MAX / 2 < n )
{
n = INT_MAX / 2;
}
int width = 1;
for ( int tmp = n; tmp /= 10; ) ++width;
putchar( '\n' );
int m = 2 * n - 1;
for ( int i = 0; i < m; i++ )
{
for ( int j = 0; j < m; j++ )
{
int value1 = abs( n - i - 1 ) + 1;
int value2 = abs( n - j - 1 ) + 1;
printf( "%*d ", width, value1 < value2 ? value2 : value1 );
}
putchar( '\n' );
}
putchar( '\n' );
}
return 0;
}
I want to know why in this statementscanf( "%d", &n ) != 1 is used
if (( scanf( "%d", &n ) != 1 ) || ( n <= 0 ));
and also how single format specifier is accepting two values here
printf( "%*d ", width, value1 < value2 ? value2 : value1 );
Why % and * are used together"%*d"??
The expression scanf("%d", &n) will attempt to read in an integer into n and, if successful, will return the value 1 (actually, it will return the number of things successfully read but, since you're only asking for one thing, that's the most you'll get back). If it fails, you'll get something else.
Hence the comparison with 1 is to ensure it worked. If you don't get 1, something went wrong.
The statement printf( "%*d ", width, something) is actually closely related to printf("%5d", something) (which would print a field at least five characters wide) but, rather than the fixed 5, the variable width is used instead.
Hence the two printf calls below are equivalent:
int val = 42;
int wid = 5;
printf("%5d", val);
printf("%*d", wid, val);
Since width always appears to be 1 in the code you've given, I'm not sure why it was done that way. It seems to me it would be easier to just use %d as the format specifier.
If you're interested in a more concise and structured solution, you may find this helpful. Don't use this if it's educational work since the intent there is to learn to do it yourself, but it's helpful to see another approach.
This code factors out the logic for doing a single line, printing enough elements to go from the maximum down to one then back up again (but setting a minimum value to print based on the line).
The main code then just prints out enough lines so that the middle value of each line goes from the maximum down to one than back up again (basically the same logic used for each line).
#include <stdio.h>
// Code to print out a single line, values going from max down to min then back up.
static void outLine(int max, int min) {
for (int i = max; i > 0; i--) printf("%d ", i < min ? min : i);
for (int i = 2; i <= max; i++) printf("%d ", i < min ? min : i);
putchar('\n');
}
int main() {
while ( 1 ) {
// Get the value, <1 means stop.
int n;
printf( "\nEnter a non-negative number (< 1 = exit): " );
if ((scanf("%d", &n) != 1) || (n <= 0)) break;
// Do each line, max down to 1 then back up.
for (int i = n; i > 0; i--) outLine(n, i);
for (int i = 2; i <= n; i++) outLine(n, i);
}
return 0;
}
Transcript is, as requested:
pax> ./testProg
Enter a non-negative number (< 1 = exit): 2
2 2 2
2 1 2
2 2 2
Enter a non-negative number (< 1 = exit): 3
3 3 3 3 3
3 2 2 2 3
3 2 1 2 3
3 2 2 2 3
3 3 3 3 3
Enter a non-negative number (< 1 = exit): 4
4 4 4 4 4 4 4
4 3 3 3 3 3 4
4 3 2 2 2 3 4
4 3 2 1 2 3 4
4 3 2 2 2 3 4
4 3 3 3 3 3 4
4 4 4 4 4 4 4
Enter a non-negative number (< 1 = exit): -42
From the C Standard (7.21.6.4 The scanf function)
Returns
3 The scanf function returns the value of the macro EOF if an input
failure occurs before the first conversion (if any) has completed.
Otherwise, the scanf function returns the number of input items assigned, which can be fewer than provided for, or even zero, in the
event of an early matching failure.
In this if statement
if (( scanf( "%d", &n ) != 1 ) || ( n <= 0 ));
the sub-expression ( scanf( "%d", &n ) != 1 ) whether the call of scanf was successful that is whether the variable n got a value from the user. If so (that is in the case of success) then the second sub-expression ( n <= 0 ) checks whether the inputted value is non-positive.
That is if either the call of scanf was not successful or the user eetered a non-positive value the control is passed outside the while loop due to the break statement. As a result the program finishes its execution.
In this call of printf
printf( "%*d ", width, value1 < value2 ? value2 : value1 );
the format conversion specifier %*d specifies that the width of the outputted field (*) will be set as an argument of the call (width) and the expression value1 < value2 ? value2 : value1 selects the maximum value between these two value value1 and value2.
You could rewrite this call pf printf the following way
if ( value1 < value2 )
{
printf( "%*d ", width, value2 );
}
else
{
printf( "%*d ", width, value1 );
}

Write a basic half pyramid pattern program

Have tried few basic pattern
trying to get pattern
1
2 4
3 6 12
4 8 16 32
SO far trying to find the proper sequence, my idea is that need another variable lets say num, and need to create a sequence for num to print num eventually
#include <stdio.h>
int main()
{
int rows = 0 , i, j , num,num2;
do{
printf("please enter the number of rows: ");
scanf("%d",&rows);
}while(rows <=2 );
printf("printing a half pyramid of %d rows", rows);
printf("\n");
for( i = 1; i <=rows; ++i) {
for (j = 1; j <= i; ++j ) {
printf("%d ", );
}
printf("\n");
}
return 0;
}
Not being able to figure out a sequence
The code you were given literally contains all the parts necessary. All that remains for you is to fill out this line inside the nested loop:
printf("%d ", ‹what goes here?›);
To find the answer you need to find how the value relates to the current row and column (give by i and j, respectively).
You don’t need an additional variable num (to be clear, you can create one, but it’s not necessary to solve this problem).
We, beginners, should help each other.:)
Here you are.
#include <stdio.h>
int main(void)
{
while ( 1 )
{
const unsigned int Base = 10;
printf( "Enter the height of a pyramid (0 - exit): " );
unsigned int n;
if ( ( scanf( "%u", &n ) != 1 ) || ( n == 0 ) ) break;
int width = 0;
unsigned int tmp = n * n;
do { ++width; } while ( tmp /= Base );
putchar( '\n' );
for ( unsigned int i = 0; i < n; i++ )
{
unsigned int value = i + 1;
for ( unsigned int j = 0; j++ <= i; )
{
printf( "%*u ", width, value * j );
}
putchar( '\n' );
}
putchar( '\n' );
}
return 0;
}
The program output might look like
Enter the height of a pyramid (0 - exit): 1
1
Enter the height of a pyramid (0 - exit): 2
1
2 4
Enter the height of a pyramid (0 - exit): 3
1
2 4
3 6 9
Enter the height of a pyramid (0 - exit): 4
1
2 4
3 6 9
4 8 12 16
Enter the height of a pyramid (0 - exit): 5
1
2 4
3 6 9
4 8 12 16
5 10 15 20 25
Enter the height of a pyramid (0 - exit): 6
1
2 4
3 6 9
4 8 12 16
5 10 15 20 25
6 12 18 24 30 36
Enter the height of a pyramid (0 - exit): 7
1
2 4
3 6 9
4 8 12 16
5 10 15 20 25
6 12 18 24 30 36
7 14 21 28 35 42 49
Enter the height of a pyramid (0 - exit): 8
1
2 4
3 6 9
4 8 12 16
5 10 15 20 25
6 12 18 24 30 36
7 14 21 28 35 42 49
8 16 24 32 40 48 56 64
Enter the height of a pyramid (0 - exit): 9
1
2 4
3 6 9
4 8 12 16
5 10 15 20 25
6 12 18 24 30 36
7 14 21 28 35 42 49
8 16 24 32 40 48 56 64
9 18 27 36 45 54 63 72 81
Enter the height of a pyramid (0 - exit): 0
The loops in the program can also look like
for ( unsigned int i = 0; i++ < n; )
{
unsigned int value = i;
for ( unsigned int j = 0; j < i; j++ )
{
printf( "%*u ", width, value );
value += i;
}
putchar( '\n' );
}
or without introducing the intermediate variable value like
for ( unsigned int i = 0; i < n; i++ )
{
for ( unsigned int j = 0; j++ <= i; )
{
printf( "%*u ", width, j * ( i + 1 ) );
}
putchar( '\n' );
}
You yourself can add a check to the program that n * n is not greater than UINT_MAX.
Edit: As you changed the displayed values in the pattern then the program can look for example the following way
#include <stdio.h>
#include <math.h>
int main(void)
{
while ( 1 )
{
const unsigned int Base = 10;
printf( "Enter the height of a pyramid (0 - exit): " );
unsigned int n;
if ( ( scanf( "%u", &n ) != 1 ) || ( n == 0 ) ) break;
int width = 0;
unsigned long long int tmp = n * ( long long unsigned )pow( 2, ( n - 1 ) );
do { ++width; } while ( tmp /= Base );
putchar( '\n' );
for ( unsigned int i = 0; i++ < n; )
{
unsigned int value = i;
for ( unsigned int j = 0; j < i; j++ )
{
printf( "%*u ", width, value );
value *= 2;
}
putchar( '\n' );
}
putchar( '\n' );
}
return 0;
}
The program output might look like
Enter the height of a pyramid (0 - exit): 10
1
2 4
3 6 12
4 8 16 32
5 10 20 40 80
6 12 24 48 96 192
7 14 28 56 112 224 448
8 16 32 64 128 256 512 1024
9 18 36 72 144 288 576 1152 2304
10 20 40 80 160 320 640 1280 2560 5120
Enter the height of a pyramid (0 - exit): 0
Tricky Pattern. Here, is a logic for that pattern with implementation.
'n' is the number of rows.
#include <stdio.h>
int main(void) {
int n = 4;
for(int i=1; i<=n; i++) {
int k=i;
printf("%d%s",k," ");
for(int j=1; j<i; j++) {
k = k*2;
printf("%d%s",k," ");
}
printf("\n");
}
return 0;
}

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.

When should I use scanf with the address of '&' ampersand key?

I have to read in a text file with names and numbers. The names represent candidates in a dummy election (7 in total) and the numbers represent the voters. If the voter number is not in the range of the 7 candidates it gets thrown out but still stored. Finally, I have to print out the results of who won the election and how many spoilt votes there were.
This is my text file:
Robert Bloom
John Brown
Michelle Dawn
Michael Hall
Sean O’Rielly
Arthur Smith
Carl White
3 8 1 3 1 6 12 9 6 5 0 2 8 4
6 6 8 3 2 8 0 12 6 1 8 3 2 2
3 2 5 7 4 11 8 6 11 12 11 7 5 5
8 9 10 12 1 3 12 12 9 11 7 9 3 1
2 10 12 7 11 9 6 6 0 1 10 7 11 2
8 0 12 8 10 11 2 2 8 4 2 12 3 2
9 1 4 8 8 7 7 4 12 2 10 10 9 4
12 9 3 12 0 4 8 0 6 5 9 0 5 3
11 6 0 3 0
This is where I am stuck about how to scan these in properly
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
FILE * data;
int spoilt=0;
typedef struct
{
int votes;
char name[20];
}candidates;
void initialize( candidates *electionCandidates, FILE *data )
{
int i;
for( i=0; i<7; i++ )
{
fscanf( data, "%[^\n]%*c", electionCandidates[i].name );
printf( "%s\n", electionCandidates[i].name );
electionCandidates[i].votes=0;
}
}
int processVotes( candidates *electionCandidates, FILE *data )
{
int i; //tallying votes
int voter;
for ( i = 0; i< 365; i++ )
{
fscanf( data, "%d", voter );
if ( voter <= 7&& voter > 0 )
electionCandidates[voter-1].votes++;
else
spoilt++;
}
//catcher to grab winner
int maxValue, winner=0;
maxValue = electionCandidates[0].votes;
for( i = 0; i < 7; i++ )
{
if( maxValue < electionCandidates[i].votes )
{
maxValue = electionCandidates[i].votes;
electionCandidates[winner] = electionCandidates[i];
}
}
return electionCandidates[winner], maxValue;
}
void printResults( candidates *electionCandidates )
{
printf("%s won the election with a total of %d votes.\n There was a total of %d spoilt"
electionCandidates[winner].name, maxValue, spoilt);
}
int main() {
data = fopen( "elections.txt","r" );
candidates electionCandidates[7];
initialize( electionCandidates, data );
processVotes( electionCandidates, data );
printResults( electionCandidates );
fclose( data );
return 0;
}
When using scanf, you must provide the address of the variable that you want to scan the result into. Provide the address by using the & operator. Also, it is a good idea to check the result of scanf to ensure that it successfully scanned what you asked for. scanf will always return the number of elements successfully scanned, unless an I/O error occurred, in which case it will return a negative number.
Here's an fixed, annotated version of your program:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct
{
int votes;
char name[20];
}candidates;
// specify a new type to hold the election result data
typedef struct
{
int winner;
int maxVotes;
int spoilt;
} electionResult;
void initialize( candidates *electionCandidates, FILE *data )
{
int i;
for( i=0; i<7; i++ )
{
fscanf( data, "%[^\n]%*c", electionCandidates[i].name );
printf( "%s\n", electionCandidates[i].name );
electionCandidates[i].votes=0;
}
}
// This function can now return more than one value, because we've wrapped
// the relevant info into a structure called "electionResult"
electionResult processVotes( candidates *electionCandidates, FILE *data )
{
// declare the election result struct here (which we fill with data)
// we initially set all values to 0
electionResult er = {0, 0, 0};
int i; //tallying votes
int voter;
for ( i = 0; i< 365; i++ )
{
// scan the vote by providing the address of voter (using &)
int result = fscanf( data, "%d", &voter );
if (result == 1)
{
if ( voter <= 7&& voter > 0 )
electionCandidates[voter-1].votes++;
else
er.spoilt++;
}
}
er.maxVotes = electionCandidates[0].votes;
for( i = 0; i < 7; i++ )
{
if( er.maxVotes < electionCandidates[i].votes )
{
// update the values in the election result struct
er.maxVotes = electionCandidates[i].votes;
er.winner = i;
}
}
return er;
}
// this function now prints the result of the election by accepting an "electionResult" struct
void printResults( candidates *electionCandidates, electionResult er )
{
printf("%s won the election with a total of %d votes.\n There was a total of %d spoilt",
electionCandidates[er.winner].name, er.maxVotes, er.spoilt);
}
int main() {
FILE *data = fopen( "elections.txt","r" );
candidates electionCandidates[7];
electionResult er;
initialize( electionCandidates, data );
er = processVotes( electionCandidates, data );
printResults( electionCandidates, er );
fclose( data );
return 0;
}
Some tips:
You can't access variables declared in other functions. You must return the data you want from one function and provide it to the other function.
Avoid having variables declared at file scope if you can. For simple programs like this, it isn't much of an issue, but in general, using global variables tends to get messy fast.
You can't return more than one value from a function unless you wrap up the values in a struct, like the above, or alternatively, have your function accept pointers to the objects that will hold the result, similar to how fscanf accepts &voter and subsequently fills the voter variable with the appropriate data (if it can).

Resources