No compiler errors, but there is a bug somewhere - c

I compiled with "gcc -ansi -pedantic -W -Wall -o ". I only get 2 errors when I compile, and here they are:
easter_eggs.c: In function ‘main’:
easter_eggs.c:23:18: warning: multi-character character constant [-Wmultichar]
if (prompt == 'egg1')
^
easter_eggs.c:23:4: warning: comparison is always false due to limited range of data type [-Wtype-limits]
if (prompt == 'egg1')
when I run the program and hit S, it displays the top 2 printf statements 2 times each. If I type anything and press enter nothing happens it just goes back to the prompt. Even if I type egg1, it still goes back to prompt. Here is the source:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char first_option;
char prompt[16];
system("clear");
system("toilet -f future -F gay Easter Eggs");
printf("\nFind all the easter eggs and you win. Simple enough.\n");
printf("Hit S to start and Q to quit\n");
scanf("%c", &first_option);
if (first_option == 's')
{
while (1)
{
printf("To exit hit Ctrl + C\n");
printf("You must find all easter eggs simply by typing stuff in the prompt below: \n");
memset(prompt, 0, sizeof(prompt));
scanf("%16s", prompt);
getchar();
if (!strcmp(prompt, "egg1"))
{
printf("Found 1\n");
}
}
}
if (first_option == "q")
{
exit(0);
}
else
{
printf("Invalid input. Press Enter to continue\n");
getchar();
main();
}
return 0;
}
Edit 1: I have edited the source
Edit 2: Changed the source again. This time I use strcmp() to compare the strings, not ==
Last Edit: I managed to make it work. Also updated the source so that it works. Thx to all for being patient with me. Havn't slept in idk how many days. :/

Read more about C programming. You are confused about char and strings.
If you want to read a word as a a string of at most 16 bytes with a terminating null byte, use e.g.
char prompt[16];
memset (prompt, 0, sizeof(prompt));
if (scanf("%15s", prompt)<1) return;
if (!strcmp(prompt, "egg1")) {
/// found
Also, you are right to compile with -Wall. But compile also with debugging information and extra warnings:
gcc -Wall -Wextra -g easter_eggs.c -o easter_eggs
and learn how to use the gdb debugger.
Read also the man pages (type man man in your Linux terminal) of scanf(3) & strcmp(3)

When you compare a char variable, you have to compare it with a char.
As the compiler told you, you have a multi-character here.
strcmp() will help you.

As mentioned in other comments, Read C. Below are some suggestions
To store string in C, You must use char[] or char * after allocating memory.
You cannot use == operator to compare strings. Use strcmp() instead.

Related

scanf keeps running nonstop

I have been trying to run the scanf() on my mac, but it never worked (took forever to run the program). Everything else like the printf works fine!
#include <stdio.h>
#include <stdlib.h>
int main(){
char name[20];
printf("What is your name? \n");
scanf("%19s", name);
return 0;
}
terminal
[Running] cd "/Users/yiminghuang/Documents/C/" && gcc scanf4.c -o scanf4 && "/Users/yiminghuang/Documents/C/"scanf4
[Done] exited with code=null in 8.611 seconds
[Running] cd "/Users/yiminghuang/Documents/C/" && gcc scanf4.c -o scanf4 && "/Users/yiminghuang/Documents/C/"scanf4
[Done] exited with code=null in 10.384 seconds
[Running] cd "/Users/yiminghuang/Documents/C/" && gcc scanf3.c -o scanf3 && "/Users/yiminghuang/Documents/C/"scanf3
[Done] exited with code=null in 15.999 seconds
I am new to C programming, so please excuse me if I fail to answer your question correctly!
Now, the program you wrote works perfectly fine but as soon as you enter a string separated by a space, it only takes the characters before the space.
To solve this problem, you can use fgets() function of C.
#include <stdio.h>
#include <stdlib.h>
#define MAX 100
int main(){
char name[MAX];
printf("What is your name? \n");
fgets(name, MAX, stdin);
printf("String = %s", name);
return 0;
}
//i have used fgets() here for getting the input
//it is a better option than gets()
//since it bounds your array and prevents buffer overflow
I have also added a printf() to check if the string is stored correctly.
IMPORTANT: fgets() also consider the newline character i.e. '\n' as a part of your string. So better to keep that in mind.
Check this question to know more about fgets()
Regards!

Not sure why optimizer is optimizing my method incorrectly

I'm new to C (so there's every good chance I'm doing something fundamentally wrong or bad), and working on a kattis problem, https://open.kattis.com/problems/abc.
I'm running in to fun with what appears to be the GCC optimiser and I'm trying to understand why or what I'm doing wrong. Here's the simplest replication case I can come up with:
#include <stdio.h>
#include <string.h>
int lookup(char input){
// This will return 2 on invalid input. Not ideal, but we don't have to worry about invalid inputs like that
fprintf(stderr, "Asked to compare: %s\n", &input);
if (strcmp("A", &input) == 0){
//fprintf(stderr, "It's an A\n");
return 0;
} else if (strcmp("B", &input) == 0){
//fprintf(stderr, "It's a B\n");
return 1;
} else {
return 2;
};
}
int main(void){
char input[3];
if (scanf("%3s", input) != 1){
fprintf(stderr, "Something went wrong reading input\n");
return -1;
};
printf("Desired Order: %s\n", input);
printf("%d %d %d\n", lookup(input[0]),
lookup(input[1]),
lookup(input[2])
);
}
An example input file for triggering this bug has a single line:
CAB
If I compile with without optimisations:
$ cc -std=gnu11 -static -lm simple.c -o simple && cat input | ./simple
Desired Order: CAB
Asked to compare: B
Asked to compare: A
Asked to compare: C
2 0 1
With optimisations enabled, note it's falling through to the else section:
$ cc -O2 -std=gnu11 -static -lm simple.c -o simple && cat input | ./simple
Desired Order: CAB
Asked to compare: B
Asked to compare: A
Asked to compare: C
2 2 2
Things I've noticed so far:
If I uncomment the fprintf after the strcmp("A", &input), the code works fine even with optimisations enabled (that's what got me wondering about optimisations breaking my code in the first place).
If I uncomment the fprintf after the strcmp("B", &input) the code fails when optimised.
If I comment out the "Desired Order:" printf, the code works fine even with optimisations.
char input[3];
but you wrote three characters to it. Need 1 more for null terminator.
char input[4];
And here we have
fprintf(stderr, "Asked to compare: %s\n", &input);
No. That's a character not a string so we want
fprintf(stderr, "Asked to compare: %c\n", input);
and we also have
strcmp("A", &input) == 0
but input is a char so we want
'A' == input
and the same for 'B'

How do I get GCC to work?

I am using Vim as my editor and GCC as my compiler, but it’s not working quite right. Let‘s say I am making a basic program to determine if a number is odd or even. Here is my code:
#include <stdio.h>
int main(int argc, char argv[])
{
int i;
printf("Enter a number: ");
scanf("%d\n", &i);
printf("%d\n", i);
if(i % 2 == 0)
{
printf("Your number is even.\n");
}
else if(i % 2 != 0)
{
printf("Your number is odd.\n");
}
else
{
printf("Invalid input.\n");
}
getchar();
return 0;
}
I'm not sure if I am programming this wrong, or gcc is just not a good compiler, or whatever. I am running linux, which I dual boot with windows. Now I press ctrl-d to stop the process, and only then does it print me back my number, and tell if it is odd or even. It isn't just this one, a lot of other programs with similar formats seem to do this to.
~ $ ./test
Enter a number: 45
45 //I press enter, nothing happends. Ctrl-d
Your number is even. //ctrl-d again
~ $
So what I'm asking is, is there a way to program it so that I don't have to quit the program in order for it to work, or is there another compiler that wouldn't have this problem? I am running on Ubuntu 14.04 dual booted with Windows 8.1.
\n in the format for scanf means "read until hit into non-whitespace character and then ignore them". Remove it and make the format for reading "%d".
to get gcc to work from vim,
goto the vim command prompt
shell gcc <and all needed parameters>
Or open another command window
set it to the same directory as the program being edited
gcc <and all needed parameters>
in general, try to make the compile step separate from the link step. I.E. to compile:
gcc -c <mySource.c> -Wall -Wextra -pedantic -std=c99 -o mySource.o
if any header files, other than those in the default 'include' path then add
-I<pathToHeaderFile>
which is often in the same directory so would be:
-I.
then link with:
gcc mySource.o -o mySource
You can add the -ggdb parameter to both lines if you plan on doing any debugging.
to add any library directories then on the link step append
-L<pathToLibrary>
to add any libraries then on the link step append, after any library parameters:
-l<shortLibName>
The initialization file for vim can contain the necessary info to invoke gcc by some keystroke combination, but I'm not totally familiar with the details.

Cannot run program

I started learning C programming with C Programming Language by Denis M Ritchie I am trying to execute program from that book
#include <stdio.h>
/* count lines in input */
main()
{
int c, nl;
nl = 0;
while ((c = getchar()) != EOF)
if (c == '\n')
++nl;
printf("%d\n", nl);
getchar();
}
However all I get is blank console and when I type text and press enter,no value is displayed.
I am using Visual Studio 2013 IDE.
The program you posted here is for counting number of lines.
Q. However all I get is blank console and when I type text and press
enter,no value is displayed
A. Yes it shows nothing because while ((c = getchar()) != EOF) waits until you enter EOF (use ctrl + z then you will get number for lines).
getchar(c);
See declaration of getchar.
int getchar(void)
It doesn't take any parameter. Didn't it gave you error.
And main should be int main.
There are several issues. First, main has to have a type, usually int
- main()
+ int main()
and your program should return an exit status
Secondly getchar takes no arguments, and returns the input
http://www.tutorialspoint.com/c_standard_library/c_function_getchar.htm
- getchar(c)
+ c = getchar()
You can compile your program by calling
gcc -Wall test.c -o test
Where test.c is your code, and test is the binary. -Wall will show all the "warning" (errors that don't interfere with the program execution)
I believe that you use Windows, it's better to add:
system("pause");
Moreover to use system("pause"), only in Windows, you need to include another library:
#include <stdlib.h>
You can see your results but the problem here, is that you have an infinite loop. Yo need to check the \n, count and when you have a specific number, you leave from the loop.

Beginner C programmer having problems with string functions

I'm a C noob, going back to school for my masters in CS so I'm taking some time to ramp up my skills. I wanted to see if anybody could lend some assistance on why I'm having problems compiling the following code. I've been following the videos on WiBit.net and develop on a 64 bit Linux environment (Ubuntu 13.10). I am using gedit and the gcc compiler no IDE.
This code runs on my Win 7 VM without errors, however when I try to execute it on my host Linux environment I'm getting errors:
Source Code: This example calls the strcmp and strcmpi functions
#include <stdio.h>
#include <string.h>
int main()
{
char str1[255];
char str2[255];
printf("str1: "); gets(str1);
printf("str2: "); gets(str2);
if(strcmp(str1, str2) == 0)
printf("Strings match exactly!");
else if(strcmpi(str1, str2) == 0)
printf("Strings match when ignoring case!");
return 0;
}
Error Message (Linux ONLY):
$gcc main.c -o demo -lm -pthread -lgmp -lreadline 2>&1
/tmp/ccwqdQMN.o: In function main':
main.c:(.text+0x25): warning: thegets' function is dangerous and should not be used.
main.c:(.text+0x8f): undefined reference to `strcmpi'
collect2: error: ld returned 1 exit status
Source Code 2: This example uses the strupr and strlwr functions
#include <stdio.h>
#include <string.h>
int main()
{
char str1[255];
char str2[255];
printf("str1: "); gets(str1);
printf("str2: "); gets(str2);
strlwr(str1);
strupr(str2);
puts (str1);
puts (str2);
return 0;
}
Error Message (Linux ONLY):
$gcc main.c -o demo -lm -pthread -lgmp -lreadline 2>&1
/tmp/ccWnIfnz.o: In function main':
main.c:(.text+0x25): warning: thegets' function is dangerous and should not be used.
main.c:(.text+0x57): undefined reference to strlwr'
main.c:(.text+0x6b): undefined reference tostrupr'
collect2: error: ld returned 1 exit status
I would love a detailed explanation if someone is willing to help and not tear me apart haha. I know that for best practices we shouldn't use gets due to buffer overflow (for example the user enters a 750 character string). Best practices would use fgets instead but my question is whether I'm getting these errors because these functions aren't part of ANSI C or what. They do show up in the man files on my machine which is throwing me through a loop.
Thanks in advance!
UPDATE:
You guys are awesome. Took all of your advice and comments and was able to revise and make a sample program for string comparison as well as conversion to upper/lower. Glad I was able to get it running on both OSes error free as well.
Sample code:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main()
{
char str[255];
printf("Enter a string: "); fgets(str,255, stdin);
printf("Here is your original string, my master: %s\n", str);
//Now let's loop through and convert this to all lowercase
int i;
for(i = 0; str[i]; i++)
{
str[i] = tolower(str[i]);
}
printf("Here is a lowercase version of your string, my master: %s\n", str);
//Now we'll loop through and convert the string to uppercase
int j;
for(j = 0; str[j]; j++)
{
str[j] = toupper(str[j]);
}
printf("Here is a uppercase version of your string, my master: %s\n", str);
return 0;
}
strcmpi problem: strcasecmp() is the posix standard and so is it in linux.
strupr and strlwr doesn't exist in glibc, although you can implement them with a single line of code, as this:
c - convert a mixed-case string to all lower case
In the compilation, first you can find a warning, because the gcc doesn't find the functions in the included header. In such cases it thinks they are declared as int funcname(void). But later, while linking, it can't find the exported symbols of this nonexistant functions, and thus it can't create the executable. This second error is what stops the compilation.
There are too many difference in the c apis, although the posix standard handles them, microsoft don't follow it.
As you noted, the gets function is unsafe because it does not perform any boundary checking: you have called it with a 255-character string buffer, but if another program wrote a line longer than 255 characters, it could write data into your process's stack, and thereby cause your process to execute malicious code (or at the very least produce a segmentation fault).
Use fgets instead:
printf("str1: "); fgets(str1, 255, stdin);
printf("str2: "); fgets(str2, 255, stdin);
If you read the error output from the compiler carefully, you'll note that it's not issuing an error on your use of gets but a warning. Your code should still compile and execute if you fix the strcmpi call.

Resources