C ambiguity problem - c

While coding very simple program for removing blanks, tabs, newlines I came across something I don't actually catch on first; even though if condition is true only when tab, space or newline doesn't exist it's still executed with the mentioned for some reason.. here is the code
#include <cstdio>
#include <cstring>
#include <stdio.h>
#include <string.h>
#define LGT 100
void rem(char s[])
{
int i;
for(i=(strlen(s)-1);i>=0;i--)
if(s[i]!=' ' || s[i]!='\t' || s[i]!='\n')
break;
s[i+1]='\0';
}
int main(void)
{
char v[LGT]={"sdsfg\t"};
rem(v);
printf("%s\n",v);
getchar();
}

s[i]!=' ' || s[i]!='\t' || s[i]!='\n' is always true. A character can't be equal to both a space, a tab and a newline.

The problem is that
  if(s[i]!=' ' || s[i]!='\t' || s[i]!='\n')
Is always true. If s[i] is a space, then the latter two checks are true. If it's not a space, them the first check is true.
To fix this, change these ors to ands:
if(s[i]!=' ' && s[i]!='\t' && s[i]!='\n')
Or, even better, use isspace:
if(isspace(s[i])

s[i] != x || s[i] != y is true for all different values of x and y.
You probably want &&.

If you think about it, any expression like the following is suspect...
a != x || a != y
Whatever a is, it will always not be one thing OR not be another. So this is always true. The equivalent mistake with and is always false rather than always true, and it looks like:
a == x && a == y
It's a little easier to see, right? Thing a can't possibly be both x AND y at the same time. And in fact these statements are related by De Morgan's laws.
Update: So, typically what you want is a != x && a != y. For the second case: a == x || a == y.

try changing
if(s[i]!=' ' || s[i]!='\t' || s[i]!='\n')
break;
with
if(s[i]!=' ' && s[i]!='\t' && s[i]!='\n')
break;

As others already pointed out, your boolean expression is a tautology (ie always true). You might also want to use the function strpbrk() instead of duplicating functionality provided by the standard library:
#include <stdio.h>
#include <string.h>
// …
char text[] = "foo\tbar\n";
char *tail = strpbrk(text, " \t\n");
if(tail) *tail = 0;
printf("<%s>", text); // prints <foo>
Also, when including <c…> headers, you should prefix identifiers with std:: or add a using directive. Alternatively, use <….h> instead.
Using functionality not inherited from the C standard library, more idiomatic C++ code would look like this:
#include <iostream>
#include <string>
// …
std::string text = "foo\tbar\n";
std::size_t pos = text.find_first_of(" \t\n");
if(pos != std::string::npos)
text.erase(pos);
std::cout << '<' << text << '>'; // prints <foo>

Related

Proper way to write 'one but not both' situation?

This question is really arbitrary so I'll try to explain it as best as I can. I'm looping through two strings of unknown size.
bool check(char *str1, char *str2)
{
char special = 'k';
for (int size_t i = 0; ; i++)
{
}
}
I want the terminating condition of the for loop to be the following:
Leave the loop only if either str1[i] == special OR str2[i] == special, but not both.
For this question, ignore the fact that I might segment fault since I know neither the size nor am I checking for 0x00.
I know how to write this but it's always really messy and involves using ternary conditional operators. What is a better way to write it?
You could use (str1[i] == special) != (str2[i] == special), as suggested here.
This works because in c, == can only return one of the int values 0 or 1 (reference).
You want the XOR operator written as ^ use it like you would and && or or ||. It is true only if one but not both arguments are true.
Oops: now see OP said "For this question, ignore the fact that I might segment fault since I know neither the size nor am I checking for 0x00."
So my concern below is moot. Leaving as a reference.
Since code is working with strings, the loop must terminate on 3 conditions:
Leave the loop if either (str1[i] == special) != (str2[i] == special), but not both.
str1[i] == 0.
str2[i] == 0.
Code code be
for (int size_t i = 0;
((str1[i] == special) != (str2[i] == special)) && str1[i] && str2[i]);
i++) {
...
}
Perhaps a simplification could be had.

What is the difference between IF and ELSE IF clauses?

I'm on the path of learning C with K&R. Besides the exercises in the book, I'm also doing some by myself. I wrote the following code, what it does is, it counts your input, gives you feedback how many words are left to reach the "goal" of 10 words and congratulates you as soon as you reach the 10 words.
#include <stdio.h>
main()
{
/* This programm will read your input, check the number of words,
and will congratulate when you reach a value of 10 words*/
int c, nw, counter;
nw = 0;
counter = 0;
while (nw < 10)
{
c = getchar();
if (c == ' ' || c == '\t' || c == '\n')
{
counter = 0;
}
else if (c != ' ' || c != '\t' || c != '\n')
{
if (counter == 0)
{
counter = 1;
++nw;
}
printf("Only %d words left\n", 10-nw );
}
}
}
Ok, in this version the code will not count blanks as words, resulting in the correct output of words left.
At first I wrote the code with only "if" instead of "else if". What it did was it also counted the blanks as words.
The question I am asking is why ? Wheres the difference in using if or else if.
As I understand is, that compiler will check whether a condition is met or not met. This should also be the case when only using if. As everything is the same expect else if instead of if, I can't figure out what the problem is.
It looks like this might be a case of overthinking a problem. The logic you've ended up with, aside from being wrong, is overly complicated. Your question of the difference between if and else if is fair, and I promise I will address it in my answer.
First, let me restate what you are trying to do:
Read input, count number of words, and congratulate you when you reach 10 words
From your code, I believe your intention is to split words based on spaces, tabs, and newlines. There are many ways to split words, but for the purposes of this question, your intended method is fine.
The problem, of course, is that your logic doesn't work. You have a condition that can never be false:
else if (c != ' ' || c != '\t' || c != '\n')
Think about it (hint: the else doesn't change the condition itself). Say it out loud if that helps: You are looking for a condition where c isn't a space, or c isn't a tab, or c isn't a newline. Remember that logical or (||) is an inclusive or, in other words, the expression is true if any of the conditions are true. For example, let's suppose c is a space. The first condition (c != ' ') fails, but the 2nd one, c != '\t' is true because a space is not a tab. Thus, the entire expression is true. In fact, that expression will be true for any value of c.
But what about else?
As I said, the else part of the else if doesn't make a difference here. The only thing else if does differently is essentially tack itself on as a new condition to your if statement. Let's look at a simpler example:
if (a == 1) {
/* a is 1 */
}
if (a != 1 && b == 2) {
/* a isn't 1, but b == 2 */
}
That's an example of two completely independent if statements. It's a perfect example of where to use else, because as you probably noticed, the 2nd if statement tests for the inverse of the 1st. (a != 1). So, the above can be simplified as follows:
if (a == 1) {
/* a is 1 */
else if (b == 2) {
/* a isn't 1 and b is 2 */
}
In the else if block, we needn't test for a != 1, as that's implied because we only evaluate the else statement if the 1st if conditional was false.
Note also that else if is actually a combination of two separate keywords. It is equivalent to:
else {
if (b == 2) { ... }
}
However, by convention we omit the optional braces and write it as:
else if (b == 2) { ... }
In fact, in some cases we don't need that 2nd if at all:
if (a == 1) {
printf("a is 1!\n");
} else {
printf("a isn't 1. In fact, it's %d.\n", a);
}
Simplified Version
So, now there's no need to get caught up in else if. Focus on your logic, and do your best to simplify it. I will simplify it for you, however I encourage you to skip over this part and try it on your own first:
char c;
int in_word = 0;
while (nw < 10) {
c = getchar();
if (c == ' ' || c == '\t' || c == '\n') {
/* If we were in a word, then count that word! */
if (in_word) {
nw++;
printf("You only have %d words to go!", 10 - nw);
}
in_word = 0; /* We are not in a word now */
} else {
in_word = 1; /* Now we're in a word
}
}
Not sure if this is the answer you are looking for. But two separate if statements are both evaluated no matter what. With "if" and "else if", first if is evaluated if it is true, else if is skipped. When "if" is not true "else if" is evaluated.
else if (c != ' ' || c != '\t' || c != '\n')
This line of code is probably not doing what you intended. It works fine as an else if, but in fact it doesn't really check anything (you could actually replace it with a simple else)! For any conceivable character, it's will always be either not a space, or not a tab, or not a newline. What you really want is the conjunction of those statements, rather than the current disjunction:
else if (c != ' ' && c != '\t' && c != '\n')
This checks that the character is neither a space, a tab, nor a newline. It would work even with else removed, as a separate if-statement. However, you really should just go with a simple else.
In your if condition, if you use simple if .. else construct, it will be equivalent to
if (c == ' ' || c == '\t' || c == '\n')
{
...
}
else if (c != ' ' && c != '\t' && c != '\n') //Notice &&.
//Apply De-morgan's law over if conditio.
{
...
}
In the above case else if is not required, if else is suffice to use. Using if .. else would be more efficient than the given code.
However, logically it may have same effect as your given code.
As per logic, else if is not required.
The difference you will get in terms of number of comparison operation as explained below.
Current code:
For any non-space character such as 'a', it will perform 4 comparisons (|| and && are short-circuited).
For any space character, there will be max 3 comparisons.
In if-else code, max of 3-comparison will be performed.
This difference is not so significant. And can only be noticed when code is run billions of times.
if else has extra advantage of maintenance. In the above code in OP, if there is any change in if part, it should be reflected in else if part also.
Hence, to me it seems it will be beneficial to go with just if else rather if else if.

Do-while loop not observing truth assignment (C) [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 7 years ago.
Improve this question
My C project is a Windows console app that takes the time signature and BPM from a user's musical project and returns the length of a bar in seconds.
I am trying to use a do-while loop to add a "continue/exit?" prompt at the end of each successful calculation
Here is the source code for that function. It performs one calculation based on user input, then terminates.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char timeSignature[6];
float BPM;
float beatsPerBar;
float barLength;
printf("Enter the working time signature of your project:");
scanf("%s",timeSignature);
beatsPerBar = timeSignature[0]-'0';
printf("Enter the beats per minute:");
scanf("%f", &BPM);
barLength = BPM / beatsPerBar;
printf("%f\n", barLength);
return 0;
}
After each successful calculation, I want to prompt the user to choose "y" to return to the initial input prompt or "n" to end the program and exit the command prompt.
This later update includes a do-while loop that is intended to add the feature.
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <unistd.h>
int main()
{
do{
char timeSignature[6];
char anotherCalculation;
float BPM;
float beatsPerBar;
float barLength;
printf("Enter the working time signature of your project:");
scanf("%s",timeSignature);
beatsPerBar = timeSignature[0]-'0';
/*
* Subtracts the integer value of the '0' character (48) from the integer value
* of the character represented by the char variable timeSignature[0] to return
* an integer value equal to the number character itself.
*/
printf("Enter the beats per minute:");
scanf("%f", &BPM);
barLength = BPM / beatsPerBar;
printf("%f\n", barLength);
Sleep(3);
printf("Would you like to do another calculation? (Y/N)");
scanf(" %c", &anotherCalculation);
}while((anotherCalculation = 'Y'||'y'));
if((anotherCalculation != 'Y'||'y'))
{
printf("Goodbye!");
return 0;
}
return 0;
}
When I compile, there are no errors, but when I run it, the program loops after ANY input. Why is the code ignoring my truth assignment? What can I do to fix this?
Change this:
while (anotherCalculation = 'Y'||'y')
To this:
while(anotherCalculation == 'Y'|| anotherCalculation == 'y')
Otherwise you're doing:
while (anotherCalculation = ('Y'||'y'))
Note I also changed the assignment = to comparison ==.
Same goes for your if later:
if (anotherCalculation != 'Y'||'y')
Should be:
if (anotherCalculation != 'Y'|| anotherCalculation != 'y')
The if is redundant by the way, you've already left the while loop, so the user does not want any more calculations.
Convert your value to an upper-case letter before doing the comparison:
while(toupper(anotherCalculation) == 'Y');
That will accept either a lower-case or upper-case 'Y', and keep your code simple and straightforward.
Your problem is with the following line of code:
while((anotherCalculation = 'Y'||'y'));
Your first problem is that you are assigning to the variable anotherCalculation and then testing that value. This is because in C the = (assignment) operators can be used in test statements and the value that was set will be returned into the statement basically making your test statement the following:
while('Y'||'y');
Also there is a fault in the logic within your test statement even after substituting the = for ==,
What you are actually doing there is the same as:
TRUE if anotherCalculation == 'Y' or if 'y'.
Since 'y' actually has a value and FALSE is 0 in standard C, your loop will continuously run because it will always have a TRUE value.
To fix all errors, what that line actually needs to be is:
while(anotherCalculation == 'Y'|| anotherCalculation == 'y');
Finally, if you want to make this code more readable and avoid double testing, you can convert the input to uppercase and test that:
while(toupper(anotherCalculation) == 'Y');
First, you're using a mathematical notation for your logical checks that makes no sense in C, and you're using the assignment = operator instead of the "test for equivalence" == operator.
}while((anotherCalculation = 'Y'||'y'));
Should be:
}while((anotherCalculation == 'Y'|| anotherCalculation == 'y'));
Second, save yourself some hassle down the road, and use fgets() to get a line of a text, and parse it.
Finally, read into things like "trailing newlines" with scanf() and fgets(). The scanf() function, for example, won't "eat up" the newline at the end of your input, and you'll get unexpected behavior. This very question appears on SO once per month at least.
Logical operators don't work like that. x == a || b doesn't evaluate as "x is equal to one of a or b"; instead, it evalutes as "x is equal to the result of the Boolean expression (a OR b)". If you want to compare x against different values, you must write it as
x == a || x == b
But you have another problem, you've used the assignment operator = where you meant to use the comparison operator ==1:
while((anotherCalculation = 'Y'||'y'))
^
|
ooops
You're performing a logical-OR of two non-zero values, which evaluates to 1 (true), and assigning the result to anotherCalculation. The result of the expression is the value of anotherCalculation after the assignment (1), so you've effectively written
while( true )
You need to use the == operator for equality comparison, and you must do an explicit comparison on each side of the || operator:
while ( anotherCalculation == 'Y' || anotherCalculation == 'y' )
You can clean this up a bit by converting your input to a specific case before doing a comparison, getting rid of the need for the || operator altogether:
while ( tolower( anotherCalculation ) == 'y' )
or
while ( toupper( anotherCalculation) == 'Y' )
1. A bright young coder named Lee
wished to loop while i was 3
When writing the =
He forgot its sequel
And thus looped infinitely
This is not doing what you expect:
}while((anotherCalculation = 'Y'||'y'));
Nor is this:
if((anotherCalculation != 'Y'||'y'))
You should be doing this:
}while((anotherCalculation == 'Y') || (anotherCalculation =='y'));
And this:
if((anotherCalculation != 'Y') && (anotherCalculation !='y'))
TLDR; Change your condition to
while( anotherCalculation == 'Y' || anotherCalculation == 'y' );

Passing an array through "isalpha" through a loop

I've been at this for quite some time now and the existing answers offer little to no help. I am new to programming and am trying to write a sub-part of my program which tries to check whether any given input is constituted solely of alphabets.
For this, the idea I have in mind is to pass an entire array through the isalpha function by using a loop which passes each character at a time. The idea makes logical sense but I am having syntactic trouble implementing it. I will greatly appreciate any help!
Below is my code-
printf("Please type the message which needs to be encrypted: ");
string p = GetString();
for (int i = 0, n = strlen(p); i < n; i++)
{
if(isalpha(**<what I'm putting here is creating the problem, I think>**) = true)
{
printf("%c", p[i]);
}
}
You should modify your code as this (assuming you have the string type defined yourself):
printf("Please type the message which needs to be encrypted: ");
string p = GetString();
for (int i = 0, n = strlen(p); i < n; i++)
{
if(isalpha(p[i]) == true) // HERE IS THE ERROR, YOU HAD =, NOT ==
{
printf("%c", p[i]);
}
}
Operator = is for assignment and operator == is for comparison!
So what was happening? The assignment resulted in true, no matter what p[i] was.
As Quentin mentioned:
if(isalpha(p[i]) == true)
could be more elegant and error prune if written like this:
if(isalpha(p[i]))
Here is an example in C:
/* isalpha example */
#include <stdio.h>
#include <ctype.h>
int main(void)
{
int i = 0;
char str[] = "C++";
while (str[i]) // strings in C are ended with a null terminator. When we meet
// the null terminator, while's condition will get false.
{
if (isalpha(str[i])) // check every character of str
printf ("character %c is alphabetic\n",str[i]);
else
printf ("character %c is not alphabetic\n",str[i]);
i++;
}
return 0;
}
Source
Ref of isalpha().
C does not have a string type.
Tip: Next time post your code as it is!
Aslo, as Alter noticed, it would be nice to use:
isalpha((unsigned char)str[i])
and in your code
isalpha((unsigned char)p[i])
for safety reasons.
Your example is here.
I.e. parameter of isalpha() is i-th character of string p. The only question is how to access to i-th character. Usually you can use []. I.e. just use following code: isalpha(p[i]) (I see that you already use [] in call of printf).
Also isalpha(p[i]) = true is wrong condition. It looks like you planned to check isalpha(p[i]) == true (you can skip == true).
Late but:
both other answers say omitting == true is desirable, but don't say it is necessary for portability.
The C core-language operators == != < <= > >= && || which return a 'logical' value use an int value of 1 for true and 0 for false. In C99 and up with stdbool.h and by common convention before that true is 1 and false is 0, so e.g. if( (a < b) == true ) will work correctly, although it is redundant and many (including me) consider it poor style. Language elements that test a logical value, namely if(c) while(c) for(;c;) and the operands to && || and the left operand to ?: consider any value that compares equal to 0 to be false, and any other value to be true.
The character-classification routines in ctype.h as well as some other standard-library routines like feof(f) and ferror(f) are specified to return some nonzero int for true and 0 (an int) for false, and on many implementations the nonzero value used for true is not (always) 1. In those cases isalpha(whatever) == true might result in testing say 4 == 1 and fail even when whatever is an alphabetic character. OTOH isalpha(...) != false or isalpha(...) != 0 does work correctly if you really want to write something explicit.

how to work with boolean function in c

Anyone please tell me, what is wrong in this code
#include<stdio.h>
bool func(char *,int);
void main()
{
char *a="Interview";
if(func(a,9))
{
printf("True");
}
else
{
printf("False");
}
}
bool func(char *s, int len)
{
if(len < 2)
return true;
else
return s[0] == s[len-1] && func(&s[1], len-2);
}
I believe this function always returns TRUE. This is an interview question. But, when I try to compile this, it shows 6 errors..
I'm going to guess it doesn't know what bool and true are. bool is not a primitive data type in C you need an extra include:
#include <stdbool.h>
The second part of your question? Does it always return TRUE?
No:
When you come into the function you'll skip the first return because your length is 9. So instead you'll return if true only if:
return s[0] == s[len-1] && func(&s[1], len-2)
Is true. You can skip the recursive logic here because it's not modifying your string, just look at the first part:
s[0] // this has to be 'I'
== // we need so what we compare against has to be 'I' as well
s[len-1] // This will be 'w'
So... that's not going to return true... who cares about ANDing (&&) the recursive part? I suspect the compiler will even optimize that out because everything here is hardcoded.
You just have to include the right header.
#include <stdbool.h>
Or, you can use _Bool type, which don't need any inclusion. bool is just an alias from this type. By the way, don't forget to compile in C99.

Resources