Display highest value in array in C - c

When I run this, ageProgMax comes out as 29 instead of what I want, 60. I did this for the smallest number of cafes that analysts drink and it worked but somehow this one doesn't.
int main()
{
char poste[] ={'P', 'P', 'O', 'A', 'P', 'A', 'P', 'P'};
int nbCafe[] ={5, 1, 3, 0, 5, 1, 0, 2};
int age[] ={25, 19, 27, 22, 49, 24, 60, 29};
int nbPers = sizeof(age) / sizeof(int);
int i;
int ageProgMax = 0;
for (i = 0; i < nbPers; i++)
if (poste[i] =='P' || age[i] > ageProgMax)
{
ageProgMax = age[i];
}
printf ("Max age of programmers : %d\n", ageProgMax);
return 0;
}
Any help?
Thanks

It's because of the || in your condition. Look at the condition you have set i.e. if (poste[i] =='P' || (age[i] > ageProgMax)). It says to store new value to ageProgMax if either of (age[i] > ageProgMax) or poste[i] =='P' becomes true. So for the last entry i.e. 29 even though (age[i] > ageProgMax) is false, the poste[i] =='P' is true and causes the overwrite of the ageProgMax's 60 with that of 29.
You can correct your program like this.
int main()
{
char poste[] ={'P', 'P', 'O', 'A', 'P', 'A', 'P', 'P'};
int nbCafe[] ={5, 1, 3, 0, 5, 1, 0, 2};
int age[] ={25, 19, 27, 22, 49, 24, 60, 29};
int nbPers = sizeof(age) / sizeof(int);
int i;
int ageProgMax = 0;
for (i = 0; i < nbPers; i++)
{
if (poste[i] =='P' && (age[i] > ageProgMax))
{
ageProgMax = age[i];
}
}
printf ("Max age of programmers : %d\n", ageProgMax);
return 0;
}

#define MAX(a,b) ((*(a)) > (*(b)) ? (a) : (b))
int *largest(int *arr, size_t size)
{
int *result = NULL;
if(arr && size)
{
if(size == 1)
{
retult = *arr;
}
else
{
result = MAX(arr, arr + 1)
arr += 2;
size -= 2;
while(size--)
{
result = MAX(result, arr);
arr++;
}
}
}
return result;
}
Returns NULL on error or pointer to the largest int.

Related

answers Can I make my code shorter using loops?

is there a way to make this code shorter?
// Points assigned to each letter of the alphabet
int compute_score(string word);
int main(void)
{
// Get input words from both players
string word1 = get_string("Player 1: ");
string word2 = get_string("Player 2: ");
// Score both words
int score1 = compute_score(word1);
int score2 = compute_score(word2);
// TODO: Print the winner
if (score1 > score2)
{
printf("Player 1 wins!\n");
}
else if (score1 < score2)
{
printf("Player 2 wins!\n");
}
else
{
printf("Tie!\n");
}
}
the calculator function
I Haved to definition character is uppercase or lower in different loops and i think i can make that in one loop but i don't know how :)
int compute_score(string word)
{
int points[] = {1, 3, 3, 2, 1, 4, 2, 4, 1, 8, 5, 1, 3, 1, 1, 3, 10, 1, 1,1, 1, 4, 4, 8, 4, 10};
int len = strlen(word);
int i = 0;
int total = 0;
for (i = 0; i <= len; i++)
{
if (word[i] >= 65 && word[i] <= 90)
{
int ascii = word[i];
int toasc = ascii - 65;
total += (points[toasc]);
}
}
int ii = 0;
int totall = 0;
for (ii = 0; ii <= len; ii++)
{
if (word[ii] >= 97 && word[ii] <= 122)
{
int asciii = word[ii];
int toascc = asciii - 97;
totall += (points[toascc]);
}
}
int totalf = total + totall;
return totalf;
}
you can try something like this:
int compute_score(string word) {
int total = 0;
int points[] = {1, 3, 3, 2, 1, 4, 2, 4, 1, 8, 5, 1, 3, 1, 1, 3, 10, 1, 1,1, 1, 4, 4, 8, 4, 10};
int len = strlen(word);
for (i = 0; i < len; i++)
if (word[i] >= 'A' && word[i] <= 'Z')
total += points[word[i] - 'A'];
else if (word[i] >= 'a' && word[i] <= 'z')
total += points[word[i] - 'a'];
return total;
}
Normalizing the current letter to upper case which allows a fixed 'A' to be used to determine the offset into the points array. Consider changing the type of point from int to static const char [] for correctness.
#include "cs50.h"
#include <assert.h>
#include <ctype.h>
#include <stdlib.h>
#define PLAYERS 2
int compute_score(string word) {
int points[] = {1, 3, 3, 2, 1, 4, 2, 4, 1, 8, 5, 1, 3, 1, 1, 3, 10, 1, 1,1, 1, 4, 4, 8, 4, 10};
int total = 0;
for (; *word; word++)
total += isalpha(*word) ? points[toupper(*word) - 'A'] : 0;
return total;
}
int main(void) {
int scores[PLAYERS];
for(size_t i = 0; i < PLAYERS; i++) {
scores[i] = compute_score(get_string("Player %d: ", i + 1));
}
// TBD: generalize print of winners
static_assert(PLAYERS == 2);
if (scores[0] > scores[1]) {
printf("Player 1 wins!\n");
} else if (scores[0] < scores[1]) {
printf("Player 2 wins!\n");
} else {
printf("Tie!\n");
}
}
If you want to generalize the print of winners then it's more direct to just remember who the winners are as you go along. For example:
#include <string.h>
// ...
int main(void) {
int max_score = -1;
char winners[PLAYERS];
for(size_t i = 0; i < PLAYERS; i++) {
int score = compute_score(get_string("Player %d: ", i + 1));
if(score > max_score)
memset(winners, 0, sizeof(winners));
if(score >= max_score)
winners[i] = 1;
}
printf("Winner(s)");
for(size_t i = 0; i < PLAYERS; i++) {
if(winners[i]) printf(" %d", i + 1);
}
printf("\n");
}
You demonstrate that you know strings are arrays of characters (with a null terminator on the end).
The following uses a "purpose-built" array that stores the points of both upper and lowercase ASCII alphabet characters.
#include <stdio.h>
int compute_score( string word ) {
char tbl[] = { // small values fit into one byte
0, 1, 3, 3, 2, 1, 4, 2, 4, 1, 8, 5, 1, 3, 1, 1,
3, 10, 1, 1, 1, 1, 4, 4, 8, 4, 10, 0, 0, 0, 0, 0,
0, 1, 3, 3, 2, 1, 4, 2, 4, 1, 8, 5, 1, 3, 1, 1,
3, 10, 1, 1, 1, 1, 4, 4, 8, 4, 10, 0, 0, 0, 0, 0,
};
int points = 0;
for( int i = 0; word[ i ]; i++ ) { // each letter of the word
int c = word[i] - '#'; // transpose down to range 0-63
if( 0 < c && c < 4*16 ) // if still in range...
points += tbl[ c ]; // then retrieve point value of this letter
}
return points;
}
int main() { // A simple test program with a few words.
string str;
str = "Hello"; printf( "'%s' %2d pts\n", str, compute_score( str ) );
str = "world"; printf( "'%s' %2d pts\n", str, compute_score( str ) );
str = "quiz "; printf( "'%s' %2d pts\n", str, compute_score( str ) );
return 0;
}
Output
'Hello' 8 pts
'world' 9 pts
'quiz ' 22 pts
EDIT: To use an even smaller "look-up table", invoke a little "modulo arithmetic"...
int compute_score( string word ) {
// point values are arrayed correspondint to ASCII character positions
uint8_t tbl[] = {
0, 1, 3, 3, 2, 1, 4, 2, 4, 1, 8, 5, 1, 3, 1, 1,
3, 10, 1, 1, 1, 1, 4, 4, 8, 4, 10, 0, 0, 0, 0, 0,
};
int points = 0;
for( int i = 0; word[ i ]; i++ )
if( word[ i ] >= 'A' )
points += tbl[ word[ i ] % 32 ];
return points;
}
EDIT2: Since we only want the look-up value for the upper two (alphabetic) ranges of the 7-bit ASCII table, AND C guarantees that the truth value of a condition will be either 0 (false) or 1 (true), the code could be made more contemporary using a "branchless programming" technique.
for( int i = 0; word[ i ]; i++ )
points += (word[i] >= 'A') * tbl[ word[ i ] % 32 ];
For other ASCII characters like digits or SP, the condition is false so no points are awarded. For characters in the right range, the points value is multiplied by 1 (the multiplication identity value).
Eventually, one's entire program can be reduced to a few lines... :-)
EDIT3: Now, turning attention to main() and its role in running the competition. Below combines (and renames) the function and its parameters.
The primary difference in this code is to recognise that each 'round' starts with zero. Subtracting the two players' scores
will give a positive number, zero, or a negative number.
Eliminating intermediary variables, each player gets a turn, their score computed, and the difference calculated all in one statement.
Then an appropriate message displayed.
Because this is fun, a do/while() loop offers the opportunity to play again.
#include <stdio.h>
#include "cs50.h"
int score( string word ) {
char pts = 0, tbl[] = {
0, 1, 3, 3, 2, 1, 4, 2, 4, 1, 8, 5, 1, 3, 1, 1,
3, 10, 1, 1, 1, 1, 4, 4, 8, 4, 10, 0, 0, 0, 0, 0,
};
for( int i = 0; word[ i ]; i++ )
pts += (word[i] > 'A') * tbl[ word[ i ] % 32 ];
word[ i-1 ] = '\0'; // trim '\n' from end before printing
printf( "'%s' - %d points\n", word, pts );
return pts;
}
int main() {
do {
int diff
= score( get_string( "Player 1: " ) )
- score( get_string( "Player 2: " ) );
if( diff > 0 )
puts( "\nPlayer 1 wins!" );
else if( diff < 0 )
puts( "\nPlayer 2 wins!" );
else
puts( "\nTie!");
} while( get_int( "\nPlay again? (0-yes otherwise ending)" ) == 0 );
return 0;
}
Output
Player 1: house
'house' - 8 points
Player 2: car
'car' - 5 points
Player 1 wins!
Play again? (0-yes otherwise ending)0
Player 1:
Alternative main() using trenary "conditional operator":
int main() {
do {
int diff
= score( get_string( "Player 1: " ) )
- score( get_string( "Player 2: " ) );
puts( diff > 0 ? "\nPlayer 1 wins!" : diff < 0 ? "\nPlayer 2 wins!" : "\nTie!" );
} while( get_int( "\nPlay again? (0-yes otherwise ending)" ) == 0 );
return 0;
}

Free invalid pointer error in C for Codewars

I am attempting to solve the Codewars problem "Sum Strings as Numbers" in which you are given two strings that are numbers and you need to return a string that is the sum of these numbers. My program works for the first few tests but it breaks down when encountering random tests with strings that are hundreds of digits long. If I use the same exact input on and run the program on my own computer, there are no issues. I get this error from code wars:
Test Crashed
Caught unexpected signal: 6
and this in stderr:
free(): invalid pointer
free(): invalid pointer
this is stdout:
START
Initial variables:
llu_strlen a = 236, llu_strlen(b) = 184
llu_strlen(s1) = 236, llu_strlen(s2) = 236
ret = 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
a: 78917474443946915721964827121804924300830503197284695927643616893992582376123210474159778186067315502131337563007456229418171820129259461866211403468685049537996202816061990624398601182936240354459414060583378547091248670096407399362798
s1: 78917474443946915721964827121804924300830503197284695927643616893992582376123210474159778186067315502131337563007456229418171820129259461866211403468685049537996202816061990624398601182936240354459414060583378547091248670096407399362798
b: 2750702483149509093439330294177302822318268374477554716003096683744873506434616984296831843933180888658289619326781012055684240461466622908813033352854623703899221940600376950489726654
s2: 00000000000000000000000000000000000000000000000000002750702483149509093439330294177302822318268374477554716003096683744873506434616984296831843933180888658289619326781012055684240461466622908813033352854623703899221940600376950489726654
entering sum loop:
i = 0, digita = 8, digitb = 4, sumstr=12
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002
i = 1, digita = 9, digitb = 5, sumstr=15
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000052
i = 2, digita = 7, digitb = 6, sumstr=14
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000452
i = 3, digita = 2, digitb = 6, sumstr=09
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009452
i = 4, digita = 6, digitb = 2, sumstr=08
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000089452
i = 5, digita = 3, digitb = 7, sumstr=10
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000089452
i = 6, digita = 9, digitb = 9, sumstr=19
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000009089452
i = 7, digita = 9, digitb = 8, sumstr=18
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000089089452
i = 8, digita = 3, digitb = 4, sumstr=08
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000889089452
i = 9, digita = 7, digitb = 0, sumstr=07
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007889089452
i = 10, digita = 0, digitb = 5, sumstr=05
(continues on like that for a while)
000000000000000000000000000121804924300830503197284698678346100043501675815453504651462600504335689979686053566104139974291678254746243758698055336649573707827615529597074046308639062649559149167492766915207082446313189270473357889089452
i = 210, digita = 7, digitb = 0, sumstr=07
000000000000000000000000007121804924300830503197284698678346100043501675815453504651462600504335689979686053566104139974291678254746243758698055336649573707827615529597074046308639062649559149167492766915207082446313189270473357889089452
i = 211, digita = 2, digitb = 0, sumstr=02
000000000000000000000000027121804924300830503197284698678346100043501675815453504651462600504335689979686053566104139974291678254746243758698055336649573707827615529597074046308639062649559149167492766915207082446313189270473357889089452
i = 212, digita = 8, digitb = 0, sumstr=08
000000000000000000000000827121804924300830503197284698678346100043501675815453504651462600504335689979686053566104139974291678254746243758698055336649573707827615529597074046308639062649559149167492766915207082446313189270473357889089452
i = 213, digita = 4, digitb = 0, sumstr=04
000000000000000000000004827121804924300830503197284698678346100043501675815453504651462600504335689979686053566104139974291678254746243758698055336649573707827615529597074046308639062649559149167492766915207082446313189270473357889089452
i = 214, digita = 6, digitb = 0, sumstr=06
000000000000000000000064827121804924300830503197284698678346100043501675815453504651462600504335689979686053566104139974291678254746243758698055336649573707827615529597074046308639062649559149167492766915207082446313189270473357889089452
i = 215, digita = 9, digitb = 0, sumstr=09
000000000000000000000964827121804924300830503197284698678346100043501675815453504651462600504335689979686053566104139974291678254746243758698055336649573707827615529597074046308639062649559149167492766915207082446313189270473357889089452
i = 216, digita = 1, digitb = 0, sumstr=01
000000000000000000001964827121804924300830503197284698678346100043501675815453504651462600504335689979686053566104139974291678254746243758698055336649573707827615529597074046308639062649559149167492766915207082446313189270473357889089452
i = 217, digita = 2, digitb = 0, sumstr=02
000000000000000000021964827121804924300830503197284698678346100043501675815453504651462600504335689979686053566104139974291678254746243758698055336649573707827615529597074046308639062649559149167492766915207082446313189270473357889089452
i = 218, digita = 7, digitb = 0, sumstr=07
000000000000000000721964827121804924300830503197284698678346100043501675815453504651462600504335689979686053566104139974291678254746243758698055336649573707827615529597074046308639062649559149167492766915207082446313189270473357889089452
i = 219, digita = 5, digitb = 0, sumstr=05
000000000000000005721964827121804924300830503197284698678346100043501675815453504651462600504335689979686053566104139974291678254746243758698055336649573707827615529597074046308639062649559149167492766915207082446313189270473357889089452
i = 220, digita = 1, digitb = 0, sumstr=01
000000000000000015721964827121804924300830503197284698678346100043501675815453504651462600504335689979686053566104139974291678254746243758698055336649573707827615529597074046308639062649559149167492766915207082446313189270473357889089452
i = 221, digita = 9, digitb = 0, sumstr=09
000000000000000915721964827121804924300830503197284698678346100043501675815453504651462600504335689979686053566104139974291678254746243758698055336649573707827615529597074046308639062649559149167492766915207082446313189270473357889089452
i = 222, digita = 6, digitb = 0, sumstr=06
000000000000006915721964827121804924300830503197284698678346100043501675815453504651462600504335689979686053566104139974291678254746243758698055336649573707827615529597074046308639062649559149167492766915207082446313189270473357889089452
i = 223, digita = 4, digitb = 0, sumstr=04
000000000000046915721964827121804924300830503197284698678346100043501675815453504651462600504335689979686053566104139974291678254746243758698055336649573707827615529597074046308639062649559149167492766915207082446313189270473357889089452
i = 224, digita = 9, digitb = 0, sumstr=09
000000000000946915721964827121804924300830503197284698678346100043501675815453504651462600504335689979686053566104139974291678254746243758698055336649573707827615529597074046308639062649559149167492766915207082446313189270473357889089452
i = 225, digita = 3, digitb = 0, sumstr=03
000000000003946915721964827121804924300830503197284698678346100043501675815453504651462600504335689979686053566104139974291678254746243758698055336649573707827615529597074046308639062649559149167492766915207082446313189270473357889089452
i = 226, digita = 4, digitb = 0, sumstr=04
000000000043946915721964827121804924300830503197284698678346100043501675815453504651462600504335689979686053566104139974291678254746243758698055336649573707827615529597074046308639062649559149167492766915207082446313189270473357889089452
i = 227, digita = 4, digitb = 0, sumstr=04
000000000443946915721964827121804924300830503197284698678346100043501675815453504651462600504335689979686053566104139974291678254746243758698055336649573707827615529597074046308639062649559149167492766915207082446313189270473357889089452
i = 228, digita = 4, digitb = 0, sumstr=04
000000004443946915721964827121804924300830503197284698678346100043501675815453504651462600504335689979686053566104139974291678254746243758698055336649573707827615529597074046308639062649559149167492766915207082446313189270473357889089452
i = 229, digita
here is the program that I run on code wars which throws an error:
#include <malloc.h>
#include <string.h>
unsigned long long llu_strlen(const char * s)
{
unsigned long long len = 0;
while (s[len])
len++;
return len;
}
char *strsum(const char *a, const char *b)
{
puts("START");
static char * ret;
char sumstr[] = "00";
char digita, digitb;
unsigned long long maxlen, i, carry;
if (llu_strlen(a) == 0 || llu_strlen(b) == 0)
return NULL;
maxlen = llu_strlen(a) > llu_strlen(b) ? llu_strlen(a) : llu_strlen(b);
// create ret full of maxlen+1 0s plus a '\0'. total size is maxlen+2
ret = (char *) malloc((maxlen+2) * sizeof(char));
for (i = 0; i < maxlen+1; i++)
ret[i] = '0';
ret[maxlen+1] = '\0';
// create copies of a and b of equal size by buffering with 0s
char s1[maxlen], s2[maxlen];
for (i = 0; i < maxlen - llu_strlen(a); i++)
s1[i] = '0';
strcpy(s1+i, a);
for (i = 0; i < maxlen - llu_strlen(b); i++)
s2[i] = '0';
strcpy(s2+i, b);
puts("Initial variables:");
printf("llu_strlen a = %llu, llu_strlen(b) = %llu\n", llu_strlen(a), llu_strlen(b));
printf("llu_strlen(s1) = %llu, llu_strlen(s2) = %llu\n", llu_strlen(s1), llu_strlen(s2));
printf("ret = %s\n", ret);
printf("a: %s\n", a);
printf("s1: %s\n", s1);
printf("b: %s\n", b);
printf("s2: %s\n", s2);
// sum loop
printf("entering sum loop:\n");
for (i = carry = 0; i < maxlen; i++)
{
digita = s1[maxlen-1-i] - 48;
digitb = s2[maxlen-1-i] - 48;
sprintf(sumstr, "%02llu", digita + digitb + carry);
carry = sumstr[0] - 48;
ret[maxlen-i] = sumstr[1];
printf("i = %llu, digita = %d, digitb = %d, sumstr=%s\n", i, digita, digitb, sumstr);
puts(ret);
}
printf("Done with that\n");
ret[0] = carry + 48;
// remove preceeding zeros
while (*ret == '0' && *(ret+1) != '\0')
ret++;
printf("final ret: %s\nEND\n\n", ret);
return ret;
}
and here is the program I run on my computer which finds the result successfully:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
unsigned long long llu_strlen(const char * s)
{
unsigned long long len = 0;
while (s[len])
len++;
return len;
}
char *strsum(const char *a, const char *b)
{
puts("START");
static char * ret;
char sumstr[] = "00";
char digita, digitb;
unsigned long long maxlen, i, carry;
if (llu_strlen(a) == 0 || llu_strlen(b) == 0)
return NULL;
maxlen = llu_strlen(a) > llu_strlen(b) ? llu_strlen(a) : llu_strlen(b);
// create ret full of maxlen+1 0s plus a '\0'. total size is maxlen+2
ret = (char *) malloc((maxlen+2) * sizeof(char));
for (i = 0; i < maxlen+1; i++)
ret[i] = '0';
ret[maxlen+1] = '\0';
// create copies of a and b of equal size by buffering with 0s
char s1[maxlen], s2[maxlen];
for (i = 0; i < maxlen - llu_strlen(a); i++)
s1[i] = '0';
strcpy(s1+i, a);
for (i = 0; i < maxlen - llu_strlen(b); i++)
s2[i] = '0';
strcpy(s2+i, b);
puts("Initial variables:");
printf("llu_strlen a = %llu, llu_strlen(b) = %llu\n", llu_strlen(a), llu_strlen(b));
printf("llu_strlen(s1) = %llu, llu_strlen(s2) = %llu\n", llu_strlen(s1), llu_strlen(s2));
printf("ret = %s\n", ret);
printf("a: %s\n", a);
printf("s1: %s\n", s1);
printf("b: %s\n", b);
printf("s2: %s\n", s2);
// sum loop
printf("entering sum loop:\n");
for (i = carry = 0; i < maxlen; i++)
{
digita = s1[maxlen-1-i] - 48;
digitb = s2[maxlen-1-i] - 48;
sprintf(sumstr, "%02llu", digita + digitb + carry);
carry = sumstr[0] - 48;
ret[maxlen-i] = sumstr[1];
printf("i = %llu, digita = %d, digitb = %d, sumstr=%s\n", i, digita, digitb, sumstr);
puts(ret);
}
printf("Done with that\n");
ret[0] = carry + 48;
// remove preceeding zeros
while (*ret == '0' && *(ret+1) != '\0')
ret++;
printf("final ret: %s\nEND\n\n", ret);
return ret;
}
int main(void)
{
char * res;
res = strsum("78917474443946915721964827121804924300830503197284695927643616893992582376123210474159778186067315502131337563007456229418171820129259461866211403468685049537996202816061990624398601182936240354459414060583378547091248670096407399362798",
"2750702483149509093439330294177302822318268374477554716003096683744873506434616984296831843933180888658289619326781012055684240461466622908813033352854623703899221940600376950489726654");
return 0;
}
The error always occurs while the print statement in the sum for loop is printing. The amount of stuff that print statement manages to print out before being cut off changes every time the program is run. This test has random strings of numbers as input, so the input changes each time. The error usually occurs when i approaches maxlen, but i can sometimes be 30-40 less than maxlen.
In your function you allocate ret in this line:
ret = (char *) malloc((maxlen+2) * sizeof(char));
you then return ret at the end of your function, presumably to be freed by the caller.
However within your function you also have these lines:
// remove preceeding zeros
while (*ret == '0' && *(ret+1) != '\0')
ret++;
This means that the the ret you are returning no longer has the same pointer value as the one you received from malloc. Then when you call free in the caller the free function doesn't know what the pointer is.
One way to fix this is to find a different way to remove leading zeros, one that doesn't change the value of ret.
These don't have room for the null terminator:
char s1[maxlen], s2[maxlen];
which makes your program write out of bounds and have undefined behavior, so make them:
char s1[maxlen+1], s2[maxlen+1];
And here you change ret, making it impossible for a user to free the malloced memory:
while (*ret == '0' && *(ret+1) != '\0')
ret++;
instead, move the part of the string that you want to keep:
char *tmp = ret;
while (*tmp == '0' && tmp[1] != '\0') tmp++;
memmove(ret, tmp, maxlen-(tmp-ret)+2);
Another detail: You declare ret as static which only makes it unsafe to use the function in a multithreaded program. It does not provide any benefits at all. Just make it:
char *ret;
Another possible improvement would be to not allocate s1 and s2 at all, but to read directly from a and b and to skip leading zeroes before doing the calculation. Example:
#define SWAP(type, x, y) \
do { \
type tmp = x; \
x = y; \
y = tmp; \
} while (0)
char *strsum(const char *a, const char *b) {
while(*a == '0' && a[1] != '\0') ++a; // skip leading zeroes
while(*b == '0' && b[1] != '\0') ++b; // skip leading zeroes
size_t lena = strlen(a);
size_t lenb = strlen(b);
if (lena == 0 || lenb == 0) return NULL;
if (lena < lenb) { // make `a` the longest string
SWAP(const char *, a, b);
SWAP(size_t, lena, lenb);
}
char *ret = malloc(lena + 2); // may add one digit + null terminator
ret[lena + 1] = '\0'; // null terminate the result
int carry = 0;
size_t i = 1;
// loop while both `b` and `a` have digits:
for (; i <= lenb; ++i) {
int sum = carry + (a[lena - i] - '0') + (b[lenb - i] - '0');
ret[lena - i + 1] = (sum % 10) + '0';
carry = sum / 10;
}
// loop while only `a` has digits:
for (; i <= lena; ++i) {
int sum = carry + (a[lena - i] - '0');
ret[lena - i + 1] = (sum % 10) + '0';
carry = sum / 10;
}
// if no carry, move everything one step to the left:
if (carry == 0) memmove(ret, ret + 1, lena + 2 - 1);
else ret[0] = carry + '0'; // carry goes to the first position
return ret;
}
Demo

How can I convert this method to become recursive?

Method checks for the amount of each character and if its even for every character, it returns 1. Otherwise, it returns 0. String is passed via str[]. chars[] has its every value set to one at the start. It's hard to picture this becoming recursive, any help on teaching is appreciated.
int recursionCheckEven(int i, int j, char str[], int chars[20]) {
for (i = 0; i < strlen(str); i+=2) {
int count = 0;
for (j = i; j < strlen(str); j+=2) {
if (str[i] == str[j] && chars[j] == 1) {
count++;
chars[i] = 2;
chars[j] = 2;
}
}
if (count % 2 != 0) {
chars[i] = 0;
}
}
for (int k = 0; k < 20; k++) {
if (chars[k] == 0) {
return 0;
break;
}
}
return 1;
}
How I call this:
for (unsigned int i = 0; i < stringcount; i++) {
int chars[20] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
if(recursionCheckEven(0, 0, strings[i], chars)) {
printf("The %dth string has even number of characters\n", i);
}
}
You can use a loop to go through the characters in a non-recursive way (this is recommended). The idea of recursion is to avoid using a loop (which is actually not recommended and wastes stack memory and causes other problems).
For recursive check, you can use pointers the check each element, then go to the next element and use the same function.
To help you get started, this is a recursive function which takes a string and counts the number of each character.
int recursive(int total, char* ptr, char ch)
{
if (*ptr == '\0')
return total;
if (*ptr == ch)
total++;
return recursive(total, ptr + 1, ch);
}
int main(void)
{
char *str = "111";
char ch = '1';
int total = recursive(0, str, ch);
printf("total of char %c in %s: %d\n", ch, str, total);
return 0;
}

Implementing bubble sort in C

I'm trying to implement a sorting function which would sort the characters from an array. Can someone tell why it's not working?
int main()
{
char tab[] = {'e', 'b', 'd', 'z', 'a', 't', '\0'};
char tab2[7] = {0};
int i = 0, j = 0, k = 0;
while (tab[i] != '\0')
{
for (j = 0; tab[j] != '\0'; j++)
{
if (tab[i] > tab2[j])
{
tab2[k] = tab[j];
k++;
}
}
k=0;
i++;
}
printf("%s\n", tab2);
return 0;
}
You '\0' has value 0 while your letters have value of 97+ for lower cases letter, so once your array is sorted the '\0' is at the very beginning.
use man ascii in the terminal or check the wikipedia link.
You can initialize your final array values at 127 and then sort the following way:
#include <stdio.h>
void swap(char *x, char *y)
{
if (x != y)
{
*x ^= *y;
*y ^= *x;
*x ^= *y;
}
}
int main()
{
char tab[] = {'e', 'b', 'd', 'z', 'a', 't', '\0'};
char tab2[7];
for (int l = 0; l < 6; l++)
tab2[l] = 127;
tab2[6] = 0;
int i = 0, j = 0;
while (tab[i] != '\0')
{
for (j = 0; tab[j] != '\0'; j++)
{
if (tab[i] < tab2[j]) // this is bubble sort, check if value is inferior
swap(&tab[i], &tab2[j]); // if it is then swap pointers
}
i++;
}
printf("%s\n", tab2);
return 0;
}
output:
abdetz

Can't loop through a string for a second time

I'm trying to implement the Vigenere Cipher, but I have a problem while trying to loop trough the key. First, all the little functions, although, I don't think the problem is there.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define ALPHANUMERIC "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" /* all alphabetic characters at their corresponding indices */
char* squeeze(char[], int);
char* formatString(char[]);
int findindex(char c);
/* squeeze: remove all occurences of c in s */
char* squeeze(char s[], int c)
{
int i, j;
for (i = j = 0; s[i] != '\0'; i++)
if (s[i] != c)
s[j++] = s[i];
s[j] = '\0';
// printf("%s\n", s);
return s;
}
/* formatString: remove all white spaces and special
characters and convert all letters to upper case */
char* formatString(char input[])
{
int i;
input = squeeze(input, ' ');
for (i = 0; input[i] != '\0'; i++)
{
if (!isalnum(input[i]))
{
input = squeeze(input, input[i]);
--i;
}
if (islower(input[i]))
input[i] = toupper(input[i]);
}
// printf("%s\n", input);
return input;
}
/* findindex: returns the predefined index of a given character */
int findindex(char c)
{
int i;
if (isdigit(c))
return 26 + c - '0';
for (i = 0; ALPHANUMERIC[i] != '\0'; i++)
if (c == ALPHANUMERIC[i])
return i;
return -1;
}
And here is the cipher-function. Just to clarify, my idea was to loop through the text-string in the for-loop and use the j-counter to loop through the codeword by setting it to zero, when it reaches the end of the codeword. All the extra printf-s are for debugging purposes.
void cipher(char codeword[], char text[])
{
int i, j;
char newword[strlen(text)];
codeword = formatString(codeword);
text = formatString(text);
printf("codeword = %s, text = %s\n", codeword, text );
j = -1;
for (i = 0; i < strlen(text); i++)
{
j++;
printf("text[i] = %c, %d, codeword = %c, %d\n", text[i], findindex(text[i]), codeword[i], findindex(codeword[i]));
newword[i] = ALPHANUMERIC[(findindex(text[i]) + findindex(codeword[j])) % 36];
printf("i = %d, j = %d\n", i, j);
if (j == strlen(codeword) - 1)
j = -1;
}
printf("%s\n", newword);
}
So, looking at the code, it all seems fine, until i run it. That's the output with input "ivcho", "ivayloivayloo":
codeword = IVCHO, text = IVAYLOIVAYLOO
text[i] = I, 8, codeword = I, 8
i = 0, j = 0
text[i] = V, 21, codeword = V, 21
i = 1, j = 1
text[i] = A, 0, codeword = C, 2
i = 2, j = 2
text[i] = Y, 24, codeword = H, 7
i = 3, j = 3
text[i] = L, 11, codeword = O, 14
i = 4, j = 4
text[i] = O, 14, codeword = , -1
i = 5, j = 0
text[i] = I, 8, codeword = , -1
i = 6, j = 1
text[i] = V, 21, codeword = , -1
i = 7, j = 2
text[i] = A, 0, codeword = , -1
i = 8, j = 3
text[i] = Y, 24, codeword = G, 6
i = 9, j = 4
text[i] = L, 11, codeword = C, 2
i = 10, j = 0
text[i] = O, 14, codeword = C, 2
i = 11, j = 1
text[i] = O, 14, codeword = :, -1
i = 12, j = 2
QGC5ZW3XHCT9Q
When the counter (j) is set to zero, it just doesn't start over and I have no idea why.

Resources