Reputation: 25
Write a program that prompts the user to enter a string and prints the goodness of the string. The goodness of a string in general, is calculated in the following way: If the string contains any letters except for 0 or 1, then its goodness is 0. Otherwise, its goodness is the number of 1's in the string.
int numZeros, numOnes, i;
char sent[50];
i = 0;
printf("Enter a string with no spaces: ");
scanf(" %s", sent);
for(i=0; i != '\0'; ++i){
if(sent[i] == '0'){
++numZeros;
}
else if(sent[i] != '\0'){
++numOnes;
}
}
if((numOnes == 0) && (numZeros == 0)){
printf("\nGoodness of the input is 0\n");
}
else if((numZeros > 0) && (numOnes == 0)){
printf("\nGoodness of the input is 0\n");
}
else{
printf("\nGoodness of the input is %d\n", numOnes);
}
return 0;
Could someone please explain why in the last else statement, when i call and try to display the value of variable "numOnes" i will get some obsure number, even if I input a specific number of 1's into a sentence?
Upvotes: 1
Views: 2141
Reputation: 58617
We can define a property called "almost-goodness" recursively, and write a recursive solution. C strings support recursion very well because if s
is a non-empty C string, then s + 1
(one byte higher address) is also a C string, representing the suffix which remains after the first character of s
.
/* almost_goodness returns -1 if the string contains
bad characters, otherwise the count of 1's. */
static int almost_goodness(const char *str)
{
switch (*str) {
case 0: /* null terminator: empty string */
return 0;
case '0':
case '1':
{
int ag_rest = almost_goodness(str + 1);
return ag_rest < 0 ? ag_rest : (*str == '1') + ag_rest;
}
default:
return -1;
}
}
int goodness(const char *str)
{
int ag = almost_goodness(str);
return ag < 0 ? 0 : ag;
}
Almost-goodness is defined as this:
If the string is empty, its almost-goodness is zero.
If the first character of the string is other than 1
or 0
, its almost-goodness is -1.
If the almost-goodness of the rest of the string is -1, the almost-goodness is -1.
Otherwise, if the first character is 1
, the almost-goodness is 1 plus the almost-goodness of the rest of the string.
Otherwise, the first character must be 0
, and the almost-goodness is that of the rest of the string.
Goodness is derived from almost-goodness by treating -1 as 0.
Here is something better: a tail recursive goodness
, with the passage of an explicit accumulator. This not allows the compiler to optimize it into a loop which means that it doesn't require an amount of stack space proportional to the length of the incoming string. As a bonus, the code is clearer, which is often the opposite with recursion rewritten to pass an accumulator:
static int almost_goodness(const char *str, int goodness_acc)
{
if (goodness_acc < 0)
return goodness_acc;
switch (*str) {
case 0:
return goodness_acc;
case '1':
return almost_goodness(str + 1, 1 + goodness_acc);
case '0':
return almost_goodness(str + 1, goodness_acc);
default:
return -1;
}
}
int goodness(const char *str)
{
int ag = almost_goodness(str, 0);
return ag < 0 ? 0 : ag;
}
Here the "(almost-)goodness accumulator" parameter goodness_ac
represents "the goodness that we know so far about some earlier part of the string that we have already seen before". If this value is -1, we don't have to bother processing the part of the string we are given.
Lastly, here is a purely iterative goodness
function:
int goodness(const char *str)
{
int g = 0;
for (; *str; str++) {
switch (*str) {
case '0':
break;
case '1':
g++;
break;
default:
return 0;
}
}
return g;
}
Very simple: loop through the string, incrementing a counter for every 1
, and skipping every 0
. If we see any other character, we bail immediately with zero regardless of the value of the counter.
Upvotes: 0
Reputation: 30926
else if( sent[i]!='0')
...
Initialize numOnes
numZeros
.
for loop will be for(i=0;sent[i]!='\0';i++)
Also you can simplify the print logic. Calculate the length of the input.
if(numZeroes+numOnes < len )
// Goodness is zero
else
// Goodness is numOnes
Implementation:
int main()
{
int numZeros=0, numOnes=0;
char sent[50];
printf("Enter a string with no spaces: ");
scanf(" %s", sent);
for(int i=0; sent[i]; ++i)
(sent[i]=='0')?numZeros++:numOnes++;
printf("Goodness of the input is %d", (numOnes+numZeros<strlen(sent))?0:numOnes);
return 0;
}
Upvotes: 2
Reputation: 488
Try this:
int main(){
int numZeros = 0, numOnes = 0, i;
bool ver = true;
char sent[50];
i = 0;
printf("Enter a string with no spaces: ");
scanf(" %s", sent);
for(i=0; sent[i] != '\0'; ++i){
if(sent[i] == '0')
++numZeros;
else if(sent[i] == '1')
++numOnes;
else{
ver = false;
break;
}
}
if(ver){
if((numOnes == 0) && (numZeros == 0))
printf("\nGoodness of the input is 0\n");
else if((numZeros > 0) && (numOnes == 0))
printf("\nGoodness of the input is 0\n");
else
printf("\nGoodness of the input is %d\n", numOnes);
}else{
printf("\nGoodness of the input is 0\n");
}
return 0;
}
You do not need any extra library.
Upvotes: 0