Getting warning in C for 'atoi' function - c

I'm currently coding for a challenge question in a book I'm reading. My code executes perfectly with the correct output, but i"m getting a warning in my code and I'm just wondering why.
I'm getting a warning on the line that reads:
int countdownStart = atoi(numInput);
The warning I'm getting says:
Implicit declaration of function 'atoi' is invalid in C99
#import <readline/readline.h>
#import <stdio.h>
int main(int argc, const char * argv[]){
printf("Who is cool? ");
const char *name = readline(NULL);
printf("%s is cool!\n\n", name);
printf("What should I start counting? ");
const char *numInput = readline(NULL);
int countdownStart = atoi(numInput);
for (int i = countdownStart; i >= 0; i--){
if (i % 3 == 0){
printf("%d\n", i);
if (i % 5 == 0){
printf("Found one!\n");
}
}
}
return 0;
}

You have to include stdlib.h
#include <stdlib.h>
Next time you encounter similar warnings just run man atoi and the manual pages should state that which header file should be included.

Related

Get output line by line from another function (another source file)?

I have two source files: counter.c and main.c:
counter.c:
#include <stdio.h>
int counter(void) {
for(int i = 0; i < 5; i++)
printf("%d\n", i);
return 0;
}
main.c:
#include <stdio.h>
int counter(void);
int main(void) {
char *line;
counter();
return 0;
}
What I want to do is to have each line that counter() prints to be assigned to the line variable so I can do printf("%s\n", line) myself in main.c.
(edit) Unfortunately, this example doesn't translate well to my actual code so maybe I'll just put it here:
https://github.com/venetwork/venet/blob/master/venet-show.c
What I need is to access the result of running this code on a line by line basis in a different source file (GTK3 GUI). The main function for my combined code will be in this file so main() in venet-show.c should be changed to, say, show(). As of this moment I just use an IO Channel (https://developer.gnome.org/glib/stable/glib-IO-Channels.html) to "stream" the output of venet-show.c to the GUI but I want to get ride of it. Any ideas?
So we pass an allocated memory address and not a pointer like you had to the function. This has storage for the result. Use the return snprintf to advance the pointer so not to overwrite previous results.
#include <stdio.h>
int counter(char *answer, size_t array_len) {
for(int i = 0; i < 5; i++)
{
size_t chars_printed = snprintf(answer, array_len, "%d\n", i);
answer+=chars_printed;
array_len-=chars_printed;
}
return 0;
}
int main(void) {
char line[10000];
counter(line, sizeof(line));
printf("%s", line);
return 0;
}

Including stdlib.h causes code to be unable to be compiled properly

I have a piece of code when I need to include stdlib.h. When I do not include this header, I have no problems compiling my code, but the moment I include the header, my code refuses to compile. It tells me that it expected an identifier or "(" before numerical constant. I have looked through my code and cannot find any issue, and as stated, the code compiles perfectly without including that header.
I am new to C, so excuse my poor code, I am simply wanting to figure out why it would be giving me this error.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int execute(char **args)
{
}
char** parse(void)
{
char command[256];
fgets(command, sizeof(command), stdin);
char delimiter[] = " ";
char * pointer = strtok(command, delimiter);
int tokens = 0;
char ** final_command;
while (pointer != NULL)
{
// final_command = (char**)realloc(final_command,
// (tokens+1)*sizeof(char*));
//printf("%s\n", pointer);
//pointer = strtok(NULL, delimiter);
}
}
int main(int argc, char **argv)
{
int EXIT_SUCCESS = 1;
do
{
printf("MyShell> ");
char ** command = parse();
} while (EXIT_SUCCESS);
return EXIT_SUCCESS;
}
I compile using the command gcc -o MyShell MyShell.c
The exact error I am getting says "error: expected identifier or '(' before numeric constant int EXIT_SUCCESS = 1;"
EXIT_SUCCESS is a standard macro (definition) in C. Do not use it as a variable name.
Like NULL, EXIT_SUCCESS is a macro defined in <stdlib.h>, if you include <stdlib.h> you must not use this identifier for other purposes.
In any case your code does not make much sense because it looks like you've got an infinite loop there in main.

How can I make my program compile without warning?

I should compile my program with spec flags to gcc. Then gcc complained about return values not taken care of. WhenI use variables to take the return values then gcc complains again:
$ gcc -pedantic -Wall -ansi -O4 miniShell.c
miniShell.c: In function ‘cd’:
miniShell.c:108:9: warning: variable ‘other_return’ set but not used [-Wunused-but-set-variable]
int other_return;
^
miniShell.c:107:12: warning: variable ‘return_value’ set but not used [-Wunused-but-set-variable]
char * return_value;
^
How can I resolve the warnings? My program is as follows.
#include <sys/stat.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <dirent.h>
#include <errno.h>
#include <stdarg.h>
#include <stdlib.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/wait.h>
#define BUFFER_LEN 1024
#define BUFFERSIZE 1024
int mystrcmp(char const *, char const *);
void err_syserr(char *fmt, ...)
{
int errnum = errno;
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
if (errnum != 0)
fprintf(stderr, "(%d: %s)\n", errnum, strerror(errnum));
exit(EXIT_FAILURE);
}
int main() {
char line[BUFFER_LEN];
char* argv[100];
char* path= "/bin/";
char progpath[20];
int argc;
size_t length;
char *token;
int i=0;
int pid;
while(1) {
i = 0;
printf("miniShell>> ");
if(!fgets(line, BUFFER_LEN, stdin)) {
break;
}
length = strlen(line);
if (line[length - 1] == '\n') {
line[length - 1] = '\0';
}
if(strcmp(line, "exit")==0) {
break;
}
token = strtok(line," ");
while(token!=NULL) {
argv[i]=token;
token = strtok(NULL," ");
i++;
}
argv[i]=NULL;
argc=i;
for(i=0; i<argc; i++) {
printf("%s\n", argv[i]);
}
strcpy(progpath, path);
strcat(progpath, argv[0]);
for(i=0; i<strlen(progpath); i++) {
if(progpath[i]=='\n') {
progpath[i]='\0';
}
}
pid= fork();
if(pid==0) {
execvp(progpath,argv);
fprintf(stderr, "Child process could not do execvp\n");
} else {
wait(NULL);
printf("Child exited\n");
}
}
return (0);
}
int mystrcmp(char const *p, char const *q)
{
int i = 0;
for(i = 0; q[i]; i++)
{
if(p[i] != q[i])
return -1;
}
return 0;
}
int cd(char *pth) {
char path[BUFFERSIZE];
char cwd[BUFFERSIZE];
char * return_value;
int other_return;
strcpy(path,pth);
if(pth[0] != '/')
{
return_value = getcwd(cwd,sizeof(cwd));
strcat(cwd,"/");
strcat(cwd,path);
other_return = chdir(cwd);
} else {
other_return = chdir(pth);
}
printf("Spawned foreground process: %d\n", getpid());
return 0;
}
Reading between the lines, I guess the original problem you were trying to solve was a warning along the lines of:
warning: ignoring return value of ‘chdir’
And you've tried to fix that by assigning the return value to a variable (which itself is now unused).
getcwd and chdir can both return error codes if they fail, which are the return values GCC is warning you about. If you want to fix the warning properly you should add logic to your code to detect and handle these error cases. Otherwise, you are potentially continuing with a state inconsistent with your assumptions (for example, you may be in an unexpected directory if getcwd failed and left your buffer in an incorrectly initialised state).
I had thought that this could be over-ridden by casting the result of the function call to void, but this does not work (you can still play tricks, but they get messy!). The GCC documentation for the warn_unused_result attribute says:
The warn_unused_result attribute causes a warning to be emitted if a
caller of the function with this attribute does not use its return
value. This is useful for functions where not checking the result is
either a security problem or always a bug,
Which suggests that you don't want to find a workaround for the warning, and should really be checking the return value for error conditions.
If you really want to do it, assign the result to a variable as you have done, then add a single use of that variable, cast to void:
int res = chdir (cwd);
/* I promise I don't need to check this return value. */
(void) res;
The other users have answered how you can get rid of the warning by fixing your code, but just for reference: If you want to 'ignore' the warnings, compile with the flag:
-Wno-unused-but-set-variable
The compiler usually gives you a tag at the end of a warning (in your case, it's -Wunused-but-set-variable). To ignore it, just change the -W to a -Wno-
Hope this helps!
There are actually 2 things wrong here in your code. The first one probably caused you to change your code, which then caused the warning you are now asking about.
I bet you the first initial warning was about chdir. As the documents say:
man chdir(3): "Upon successful completion, 0 shall be returned.
Otherwise, -1 shall be returned, the current working
directory shall remain unchanged, and errno shall be set to
indicate the error."
As it says, chdir can return an error code stating if anything went wrong and the first initial warning was caused due to the fact you simply ignored that value.
Then you changed your code and assigned the value to another variable and got:
warning: variable ‘other_return’ set but not used [-Wunused-but-set-variable]
int other_return;
and you can see in this function that you are only setting a value to that variable but don't actually use it later which means you can delete it:
int cd(char *pth) {
char path[BUFFERSIZE];
char cwd[BUFFERSIZE];
char * return_value;
int other_return;
strcpy(path,pth);
if(pth[0] != '/')
{
return_value = getcwd(cwd,sizeof(cwd));
strcat(cwd,"/");
strcat(cwd,path);
other_return = chdir(cwd);
} else {
other_return = chdir(pth);
}
printf("Spawned foreground process: %d\n", getpid());
return 0;
}
Same thing for return_value. You can simply delete them both since they are not in use.
In case you want to avoid the first initial warnings you can always do something like this:
int res = chdir (cwd);
(void) res;
This is an assurance made by you to the compiler that everything is fine and he can ignore the warning.

Whats wrong with this basic shell program? it will run fine for the first few commands but results always ends in a seg fault

I have to build a simple shell program using lex and c code. The lex portion is for breaking down the input. It has been provided for me and I'm not expected to change it. I'm in the process of getting my code to run basic commands like "ls". It seems to work the first few times I run the command but eventually always seg faults. Here is the lex code provided:
%{
int _numargs = 10;
char *_args[10];
int _argcount = 0;
%}
WORD [a-zA-Z0-9\/\.-]+
SPECIAL [()><|&;*]
%%
_argcount=0;
_args[0]=NULL;
{WORD}|{SPECIAL} {
if(_argcount < _numargs-1) {
_args[_argcount++]= (char *)strdup(yytext);
_args[_argcount]= NULL;
}
}
\n return (int)_args;
[ \t]+
.
%%
char **getln() {
return (char **)yylex();
}
This is the C code:
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/wait.h>
extern char **getln();
int main() {
int i;
char **args;
int child1;
int status1;
int counter=0;
int argCount = 1;
char **array = (char **)malloc(1500 * sizeof(char *));
for (i = 0; i < 1500; ++i) {
array[i] = (char *)malloc(500);
}
strcpy(array[0],"ls\0");
array[1] = NULL;
while(1) {
args = getln();
printf("is error here?");
strcpy(array[0], args[counter]);
for(i = (counter+1); args[i] != NULL; i++) {
printf("\nRight before copying to subarray");
strcpy(array[argCount], args[i]);
argCount++;
}
array[argCount] = NULL;
if (strcmp(args[counter],"exit")==0) exit(0);
child1 = fork();
if(child1==0){
execvp(array[0], array);
printf("Unknown command, please try again.");
exit(1);
}
else{
while (wait(&status1) != child1);
}
for(i = 0; args[i] != NULL; i++) {
printf("Argument %d: %s\n argCount: %d", i, args[i], argCount);
}
argCount = 1;
counter++;
}
}
Thanks in advance for any advice. If there is some simple way to adjust the getln() function to overwrite the args array each time it is called that might be easier than what I am attempting but I have no idea how to go about that.
It seems like you have put
_argcount=0;
_args[0]=NULL;
at the top of the rules section in hopes that these statements would be executed at the beginning of yylex(). And you've noticed that they aren't executed (it keeps appending to the previous values because _argcount never goes back to 0).
The obvious thing to do is move those statements into getln() just before the yylex().
What you have now is a lexer that will ignore the string _argcount=0; in the input because it will match that pattern and there's no action to go with it. The second line is even cooler since the [0] is a character class. It makes the lexer ignore the string _args0=NULL;

Why can't I call my function(C)?

This is part of a program where I call a function that reads components from a ".dat" file and save the input to members of a Struct. When I try calling the function from my main.c it gives various errors depending on what I try. Most notably: conflicting types of 'ReadFile' and too few arguments to function 'ReadFile'. I also get a warning "passing argument from 'ReadFile' makes integer from pointer without cast" and some infos.
This is main.c
#include "MyData.h"
#include "NodalA.h"
#include "FileHandling.h"
#include <stdio.h>
#include "windows.h"
int main(){
ComponentType *CircuitData;
int numComp = 6;
int numEl = 0;
int numNodes = 0;
CircuitData = malloc((numComp)*sizeof(ComponentType));
ReadFile(CircuitData, &numEl, &numNodes);
return 0;
}
This is FileHandling.c:
#include "FileHandling.h"
#include "stdio.h"
void ReadFile(ComponentType *CircuitData, int *numEl, int *numNodes){
numEl = 0;
numNodes = 0;
int index = 0;
FILE *data;
data = fopen("mydata.dat", "r");
if (data == NULL){
printf("Error: \"mydata.dat\" could not be opened");
}
else {
while(!feof(data)){
fscanf(data, "%s, %s, %s, %f", CircuitData[index].name, CircuitData[index].node1, CircuitData[index].node2, CircuitData[index].value);
*CircuitData[index].node1 = extractInteger(CircuitData[index].node1);
*CircuitData[index].node2 = extractInteger(CircuitData[index].node2);
if(*CircuitData[index].node1 > *numNodes)
*numNodes = *CircuitData[index].node1;
if(*CircuitData[index].node2 > *numNodes)
*numNodes = *CircuitData[index].node2;
numEl++;
index++;
}
}
fclose(data);
}
And this is MyData.h
#ifndef MYDATA_H_
#define MYDATA_H_
typedef struct Comp{
char name[5]; //Name of circuit component
char node1[5], node2[5]; //2 nodes
float value[5]; //value
}ComponentType;
#endif /* MYDATA_H_ */
Any help would be appreciated. There are more code but I think this is the most important part.
The ReadFile function name used in the program is the same as a ReadFile function in "windows.h". The error "too few arguments to function 'ReadFile'" is most likely caused by the program trying to call the the function from windows with the wrong arguments. Removing "windows.h" or renaming the function ReadFile to something else solves the problem.

Resources