stack smashing in string and infinite loop - c

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

Related

C program that uses functions to verify security codes

I'm trying to write a program that uses the Luhn algorithm to verify security codes. The program needs to:
read security codes from a file and enter them into an array
use one function to read the security codes
use another function to verify them
to verify them, the digits in the odd position will be summed together. The digits in the even positions will be multiplied by two; once they're multiplied by two, if the number is less than ten, it is added to a sum of the evens; if it's more than ten, the sum of the digits of the number are added to the sum of the evens. So, if the number in the second position in the array is 8, it's multiplied by 2 to get 16, then 1 + 6 = 7 is added to the sum of the evens. There's more to verifying the codes, but this is the part I'm working on right now.
The problems I have: I don't think my function for scanning the codes from the file is correct. Each of the codes in the file has 20 digits so when I was declaring the array variable I did: int sc[20]. However, there's more than one 20 digit security code, and I'm not sure how to fix that.
And second: I'm not sure how to approach the second part of summing the evens (the part where if the number multiplied by two is greater than ten, it's digits are added to the sum of the evens).
This is the first few lines from the file (the entire file is very long so I'm just listing the first few lines):
0 7 6 1 1 6 6 2 6 8 5 1 5 5 7 7 7 8 0 2
2 5 1 6 2 1 8 2 4 3 0 9 1 9 1 1 3 1 3 8
1 3 3 4 5 4 5 2 8 6 1 8 9 3 7 6 2 2 0 5
And this is my code so far:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <math.h>
ReadSecurityCode(FILE* codes, int sc[]);
int main(void) {
int sc[20], i;
FILE* codes;
codes = fopen("SecurityCodes.txt", "r");
while (fscanf(codes, "%c\n", &sc) != EOF) {
ReadSecurityCode(codes, sc[20]);
}
fclose(codes);
return(0);
}
int ReadSecurityCode(FILE* codes, int sc[]) {
int i;
for (i = 0; i < 20; i++) {
fscanf(codes, "%d", &sc[i]);
}
return(sc[20]);
}
int isCodeValid(int sc[]) {
int i, sumodds = 0, sumevens = 0, sumtotal;
for (i = 1; i < 20; i = i + 2) {
sumodds = sumodds + sc[i];
}
for (i = 0; i < 20; i = i + 2) {
sc[i] = sc[i] * 2;
if (sc[i] < 10) {
sumevens = sumevens + sc[i];
}
else {
}
}
return(sumtotal);
}
The easiest option is to read and validate each line as you go. In the code you posted, this means calling isCodeValid() in while loop where you read the records:
while (fscanf(codes, "%c\n", &sc) != EOF) {
ReadSecurityCode(codes, sc);
isCodeValid(sc);
}
Consider using a char instead of int to store each digit (i.e. char sc[20]).
Not sure why ReadSecurityCode returns the first element, but scanf() can fail, so you might want to return an error code instead and check it. Also, I suggest that you use ReadSecurityCode() to read a line including the newline.
You probably also want to do something based the return value of isCodeValid(). The is-naming suggest you are returning a boolean but you are returning a sum.
With the above suggestions it would be:
while (!ReadSecurityCode(codes, sc)) {
if (!isCodeValid(sc)) {
printf("%s is invalid\n", sc);
}
}

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,

Process data from char array

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.

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.

Calculating total number of adjacent integers

I want to calculate the number of integers excluding repeats line by line from the file.
The output I desire is:
Duplicates : 9
Duplicates : 4
Duplicates : 5
Duplicates : 5
Duplicates : 1
Duplicates : 1
Duplicates : 8
For further explanation of the concept:
Take the second line of the file:
1 2 3 4 5 6 5 4 5
At this line there is a 1 so increment the counter because 1 was found first.
Next comes a 2, 2 is not 1 so increment the counter. Next comes a 3, 3 is not a 2 so increment the counter. Next comes a 4, 4 is not a 3 so increment the counter. Next comes a 5, 5 is not a 4 so increment the counter. Next comes a 6, 6 is not a 5 so increment the counter. Next comes a 5, 5 is not a 6 so increment the counter. Next comes a 4, 4 is not a 5 so increment the counter. Next comes a 5, 5 is not a 4 so increment the counter. The number of integers excluding repeats is 9.
Another example:
Take a look a line 8 of the file:
34 34 34 34 34
At this line there is a 34 so increment the counter. Next comes a 34, 34 is 34 so do not increment the counter. Next comes 34, 34 is 34 so do not increment the counter. Next comes a 34, 34 is 34 so do not increment the counter. Next comes a 34, 34 is 34 so do not increment the counter. The number of integers excluding repeats is 1.
EDIT:
I took the suggestion of a user on here and looked at a few link related to adjacent strings and integers. The output is almost completely correct now when compared to the desired output that I listed above. I will only put the pertain code below:
Output:
check1:1
check1:1
check1:2
Duplicates : 6 (Wrong value)
check1:2
Duplicates : 5 (Wrong value)
Duplicates : 5
Duplicates : 5
check1:0
check1:0
check1:0
check1:0
Duplicates : 1
Duplicates : 1
check1:0
check1:0
check1:2
check1:3
check1:3
check1:3
check1:4
check1:5
check1:5
check1:5
check1:5
check1:6
check1:6
Duplicates : 7 (Wrong value)
From the output it appears that whenever a test case goes through the if statement if(array[check] == ch), the output is incorrect.
I have been staring at the loops in this function for a long and I am still stumped.
Any suggestions as to why that loop is leading to incorrect values? Thank you.
Your logic is too complicated, this simple logic should do it
Count the first value
Start a loop from the second value to the last
Subtract the current value from the previous, if the result is 0 then it's the same value, do not add to the counter otherwise add to the counter.
I wrote a program to show you how
numbers.txt
1 2 3 4 5 6 5 4 5
14 62 48 14
1 3 5 7 9
123 456 789 1234 5678
34 34 34 34 34
1
1 2 2 2 2 2 3 3 4 4 4 4 5 5 6 7 7 7 1 1
program.c
#include <stdlib.h>
#include <stdio.h>
int
main(int argc, char **argv)
{
FILE *file;
char line[100];
file = fopen("numbers.txt", "r");
if (file == NULL)
return -1;
while (fgets(line, sizeof(line), file) != NULL)
{
char *start;
int array[100];
int count;
int value;
int step;
count = 0;
start = line;
while (sscanf(start, "%d%n", array + count, &step) == 1)
{
start += step;
count += 1;
}
fprintf(stderr, "%d ", array[0]);
value = 1;
for (int i = 1 ; i < count ; ++i)
{
value += (array[i] - array[i - 1]) ? 1 : 0;
fprintf(stderr, "%d ", array[i]);
}
fprintf(stderr, " -- %d\n", value);
}
fclose(file);
return 0;
}
You simply need to check the current value to previous value of the array and check if they are equal or not something like this ::
int ans = 1;
for (int i = 1 ; i < n ; i++) { //n is the number of elements in array
if (a[i] != a[i - 1]) {
ans++;
}
}
printf("%d", ans);
I do not exactly understand why you use so many check in your code. What I do in this code is that I check my current element in the array (starting from 1) and compare it with previous element, so if they are not equal you have a unique element in your array (sequentially), and hence I increment the ans which is the number of unique elements sequentially.
Here I start with ans = 1 because I assume that there will be at least 1 element in your array and that will be unique in any case.
I don't know what you are using that much code for.
But for what i understand you want to do, it a simple loop like this:
#include <stdio.h>
int main() {
int array[] = {1,3,5,7,9};
int count = 1;
int i = 0;
for(i=1; i<(sizeof(array)/sizeof(array[0])); i++) { //sizeof(array)/sizeof(array[0]) calculates the length of the array
if(array[i]!=array[i-1]) {
count++;
}
}
printf("%d", count);
}

Resources