Why are my pointer assignments causing program to crash - c

I have written the code below as a small program to test out before writing a larger program based on the same basic principle. I had it working yesterday, but it's getting hung up this morning, and I can't figure out why.
The code is getting hung up at: new_rec->next = head;
Please have a look at the code below, and thanks for your help.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
FILE *fptr;
struct list {
char string[256];
char *ptr;
struct list *next;
};
unsigned int breakRemove(char string1[]);
int main(void)
{
if ((fptr = fopen("C:\\Users\\mgreene\\Documents\\EmailTemplates\\TestList.txt", "w")) == NULL)
{
fprintf(stderr, "Error opening file.");
exit(1);
}
int i, j, k, count=0;
char ans[256];
char *pAns;
pAns = ans;
struct list *ptr = NULL;
do
{
puts("\nEnter some text: ");
fgets(ans, 256, stdin);
breakRemove(ans);
if (pAns != '\0');
{
count++;
printf("\n%d. You typed:\"%s\"", count, pAns); //test for correct pAns pointer assignment
}
struct list list1;
struct list *head = NULL;
struct list *new_rec = NULL;
struct list *curr_rec = NULL;
struct list *next_rec = NULL;
new_rec = (struct list*)malloc(sizeof(struct list));
if (!new_rec)
{
puts("\nMemory Allocation Error");
exit(1);
}
puts("\nFirst Memory Allocation Successful."); //acknowledge successful memory allocation
ptr = pAns;
printf("\nptr = %s", ptr); //test for pointer assignment
printf("\npAns = %s", pAns); //test for pointer assignment
head = ptr;
printf("\nhead = %s", head);// test for pointer assignment
printf("\nProblem is new_rec->next=head."); //test to isolate problem.
new_rec->next = head;
printf("\nnew_rec->next = ", new_rec->next);
head = new_rec;
curr_rec = head;
while (curr_rec->next != NULL)
{
curr_rec = curr_rec->next;
}
puts("\nList Pointer Memory Allocation Successful.");
curr_rec->next = new_rec;
new_rec->next = NULL;
strcpy(new_rec->string, ans);
printf("\n%s", curr_rec->string);
if (list1.string != '\0')
{
fprintf(fptr, "\n%d. %s", count, curr_rec->string);
}
}while (*pAns != '\0');
}
unsigned int breakRemove(char string1[]) //Function for removing line breaks from fgets.
{
unsigned int lenString;
lenString = strlen(string1);
if (string1[lenString-1]=='\n')
{
string1[lenString-1]='\0';
}
return (unsigned char)string1;
}

Enable the warnings in your compiler. I got:
../main.c:53:9: warning: assignment from incompatible pointer type [enabled by default]
../main.c:54:5: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘struct list *’ [-Wformat]
../main.c:57:5: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘struct list *’ [-Wformat]
../main.c:62:5: warning: too many arguments for format [-Wformat-extra-args]
../main.c:44:18: warning: unused variable ‘next_rec’ [-Wunused-variable]
../main.c:23:13: warning: unused variable ‘k’ [-Wunused-variable]
../main.c:23:10: warning: unused variable ‘j’ [-Wunused-variable]
../main.c:23:7: warning: unused variable ‘i’ [-Wunused-variable]
../main.c: In function ‘breakRemove’:
../main.c:93:10: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
Fix them for a good start. :)
For example, the first warning is coming from
ptr = pAns;
and then this will be head. That's why your program crashes (one of the reasons probably).
You have
char *pAns;
struct list *ptr = NULL;
and then you assign the one to the other. This doesn't make sense. You should try/study harder, since the errors are many for an answer to fix them.
Another example is here:
if (pAns != '\0')
; <-- suspicious semicolon, remove it
{
count++;
printf("\n%d. You typed:\"%s\"", count, pAns); //test for correct pAns pointer assignment
}
To turn the warnings on in code blocks, you could do this:
"check the option "Enable all compiler warnings" in the settings=>configure plugins=>compiler"
or do this:
that I found here.

Related

C Pointer Error

The program below is supposed to read a txt file and put the data in a struct. But it gives an pointer error. It gives an error in strcpy() about pointers. I'm new in C. Whats wrong?
#include <stdio.h>
#include <string.h>
int main()
{
struct citydata {
char city[20];
int temp;
};
struct citydata values[15];
struct citydata Avg;
struct citydata high;
struct citydata low;
FILE* inp;
int reccount = 0;
int x = 0;
char s;
int n;
inp = fopen("mydata.txt", "r");
if (!inp) {
printf("Unable ot open file\n");
}
while (fscanf(inp, "%s %d", s, &n) != EOF) {
strcpy(values[x].city, s);
values[x].temp = n;
x++;
}
fclose(inp);
}
Don't ignore compiler warnings.
When if you compile this code (say, with gcc), you get the following warnings:
test.c:27:24: warning: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘int’ [-Wformat=]
while (fscanf(inp, "%s %d", s, &n) != EOF) {
^
test.c:28:32: warning: passing argument 2 of ‘strcpy’ makes pointer from integer without a cast [-Wint-conversion]
strcpy(values[x].city, s);
^
In file included from test.c:2:0:
/usr/include/string.h:125:14: note: expected ‘const char * restrict’ but argument is of type ‘char’
extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
so, as comments suggest, you can't scan directly into the struct; you can only scan into simpler types the C standard libraries recognizes: integer, floating-point numbers, char * strings etc. Similarly, you can't perform a string copy from your structs, which are not strings.
C is a strongly-typed language with very few allowed implicit conversions. In some cases, you are able to pass integers instead of floats or vice-versa, but nothing "magically converts" into a string, or is "magically parsed" from a string.
... and there are other issues:
Note #EdHeal 's comment: If your fopen() fails, you mustn't continue running the rest of the code. Either you should exit(EXIT_FAILURE); or wrap the rest of the code in main() within an else() block.
You should printf error messages to the standard error stream, so instead of printf("error message here") it should fprintf(stderr,"error message here"). Also, the standard C library places an error code you can get as the errno variable, or you can have an error message printed to the standard error stream with the perror() function. There are a few other related related functions (like strerror(), `err() etc.) which I will not get into here.
make some mistakes with pointers=)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct citydata
{
char *city;
int temp;
} citydata;
int main()
{
char *s;
citydata *values;
values = (citydata*)malloc(sizeof(citydata) * 16);
FILE * inp;
int reccount = 0;
int x = 0;
int n;
inp = fopen("mydata.txt", "r");
if(!inp)
printf("Unable ot open file\n");
while (fscanf(inp,"%s %d",s, &n) != EOF)
{
values[x].city = (char*)malloc(sizeof(char) * 20);
strcpy(values[x].city, s);
values[x].temp = n;
x++;
}
fclose(inp);
}

Reading data from a file into a structure array (C)

I'm trying to build a simple function that will take in a data file, and assign various values from the data file into a global array of structures. However, I'm having trouble getting it to work quite right. I've written what I believe is most of the needed code, but my test line printf("time is %d\n", BP[i].time); simply reads out "Time is 0." 10 times, leading me to believe the values aren't getting assigned to the structure array like I imagined they would be.
How can I proceed further?
Example Data File (.txt):
0001 553 200
0002 552 100
.... ... ...
Current Code:
#include <stdio.h>
#include <stdlib.h>
// Function Prototype
void readFileBP(char fileName[1000]);
// Definition of BP Structure
struct bloodPressure
{
int *time;
int *sys;
int *dia;
}BP[50]; // end struct BP
int main()
{
char fileName[1000] = "C:\\Users\\User\\Desktop\\DataFiles\\BP_1.txt";
readFileBP(fileName);
int i = 0;
for (i; i<10; i++)
{
printf("Time is %d\n", BP[i].time);
}
} // end int main()
void readFileBP(char fileName[1000])
{
FILE *filePtr; // declare file pointer
int time;
int sys;
int dia;
int position = 0;
if (filePtr = fopen(fileName, "r") == NULL) // error check opening file
{
printf("Opening file failed. Please reenter filename.");
exit(1);
} // end if
while (fscanf(filePtr, "%d, %d, %d", &time, &sys, &dia) != EOF) // read in BP values
{
BP[position].time = time;
BP[position].sys = sys;
BP[position].dia = dia;
position++;
} // end while
fclose(filePtr);
} // end void readFile()
Compile with warnings enabled. You should get something like that:
gsamaras#gsamaras-A15:~$ gcc -Wall -o px px.c
px.c: In function ‘main’:
px.c:22:5: warning: statement with no effect [-Wunused-value]
for (i; i<10; i++)
^
px.c:24:9: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat=]
printf("Time is %d\n", BP[i].time);
^
px.c: In function ‘readFileBP’:
px.c:37:17: warning: assignment makes pointer from integer without a cast [enabled by default]
if (filePtr = fopen(fileName, "r") == NULL) // error check opening file
^
px.c:37:5: warning: suggest parentheses around assignment used as truth value [-Wparentheses]
if (filePtr = fopen(fileName, "r") == NULL) // error check opening file
^
px.c:45:27: warning: assignment makes pointer from integer without a cast [enabled by default]
BP[position].time = time;
^
px.c:46:26: warning: assignment makes pointer from integer without a cast [enabled by default]
BP[position].sys = sys;
^
px.c:47:26: warning: assignment makes pointer from integer without a cast [enabled by default]
BP[position].dia = dia;
^
px.c: In function ‘main’:
px.c:26:1: warning: control reaches end of non-void function [-Wreturn-type]
} // end int main()
^
Isn't that enough to get you started? It was for me! :)
I made some changes and ran it just now.
#include <stdio.h>
#include <stdlib.h>
// Function Prototype
void readFileBP(char fileName[1000]);
// Definition of BP Structure
struct bloodPressure
{
int time;
int sys;
int dia;
}; // end struct BP
struct bloodPressure BP[50];
int main()
{
char *fileName = "file.txt";
readFileBP(fileName);
int i = 0;
for (i; i<10; i++)
{
printf("Time is %d\n", BP[i].time);
}
getch();
}
void readFileBP(char fileName[1000])
{
FILE *filePtr; // declare file pointer
int time=0;
int sys=0;
int dia=0;
int position = 0;
filePtr= fopen(fileName,"r");
while (fscanf(filePtr, "%d, %d, %d", &time, &sys, &dia) != EOF) // read in BP values
{
BP[position].time = time;
BP[position].sys = sys;
BP[position].dia = dia;
position++;
} // end while
fclose(filePtr);
} // end void readFile()
The output is now:
Time is 1
Time is 553
Time is 200
Time is 2
Time is 552
Time is 100
Time is 0
Time is 0
Time is 0
Time is 0
try changing the line :
while (fscanf(filePtr, "%d, %d, %d", &time, &sys, &dia) != EOF)
to
while (fscanf(filePtr, "%d%d%d", &time, &sys, &dia) != EOF)
also here's what i tried out and it seems to work based on the tests i've done
#include <stdio.h>
#include <stdlib.h>
#define MAX_ARRAY_SIZE 50
typedef struct BloodPressure
{
int time;
int sys;
int dia;
}BloodPressure;
BloodPressure bloodPressure[MAX_ARRAY_SIZE];
void ReadFile(char *fileName);
int main(int argc, char *argv[])
{
char *fileName = "BP_1.txt";
ReadFile(fileName);
int i = 0;
for (i = 0; i < MAX_ARRAY_SIZE; i++)
{
printf("Dia is : %d\n", bloodPressure[i].dia);
printf("Sys is : %d\n", bloodPressure[i].sys);
printf("Time is : %d\n", bloodPressure[i].time);
printf("\n");
}
exit(EXIT_SUCCESS);
}
void ReadFile(char *fileName)
{
FILE *filePtr = NULL;
int i = 0;
if ((filePtr = fopen(fileName, "r")) == NULL)
{
printf("Error : Unable to open %s for reading\n");
exit(EXIT_FAILURE);
}
while (fscanf(filePtr, "%d%d%d", &bloodPressure[i].dia, &bloodPressure[i].sys, &bloodPressure[i].time) != EOF)
{
i++;
}
fclose(filePtr);
}

Arrays and Structs

I am taking an online college course introducing C and am completely stumped on my latest project. My professor to research online for the errors but the examples don't seem to match. I started the program on Visual Studio 2013 and now have moved to Code::blocks from the professor's instruction.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
typedef struct flightRec { // declare a struct to match the format of the binary data
char FlightNum[7];
char OriginAirportCode[5];
char DestAirportCode[5];
int timestamp;
} flightRec;
int flightCmp(const void *a, const void *b) // comparison function of DestAirportCode to ascending order
{
const flightRec *p1 = (flightRec *)a;
const flightRec *p2 = (flightRec *)b;
if (p1->DestAirportCode < p2->DestAirportCode)
return -1;
else if (p1->DestAirportCode > p2->DestAirportCode)
return +1;
else
return 0;
}
int codeInst(int count, int i, char currCode, char nextCode, flightRec flightInfo[1000]) { // function that counts how many instances of each code exist
count = 0; // set count to zero
i = 0;
currCode = flightInfo[i].DestAirportCode; // get a code from the array, call it currCode
while (i < 1000 ) { // while you've not come to the end of the array
nextCode = (&flightInfo[i+1].DestAirportCode); // get the next code from the array
if (nextCode == currCode) { // if the next code equals the current code
count += 1; // then add one to count
}
else {
printf("Destination Airport Code: %s Count: %i", flightInfo->DestAirportCode, count); // else output code and count
currCode = nextCode; // set currCode to nextCode
count = 0; // set count to 0
}
++i;
}
}
int main(){
flightRec flightInfo[1000];
int i = 0;
int codeInst;
FILE* inFile = NULL;
inFile = fopen("acars.bin", "rb");
struct tm* timestamp;
if (inFile == NULL) {
printf("Could not open file acars.bin.\n");
return -1;
}
while (!feof(inFile)) {
for (i = 0; i < 1000; ++i) {
fread(&flightInfo[i], sizeof(flightInfo), 1, inFile); // read the acars.bin file into an array of these structs
}
for (i = 0; i < 1000; ++i) {
qsort(flightInfo, 1000, sizeof flightInfo, flightCmp); // sort the array
}
for (i = 0; i < 1000; ++i) {
localtime(flightInfo[i].timestamp); // Do localtime () on the timestamp member of the struct, then asctime on the time struct you get back from localtime
return timestamp;
}
int codeInst(flightInfo); // algorithm to count how many instances of each code exists
for (i = 0; i < 1000; ++i) {
printf("Flight Number: %s \nOriginal Airport: %s \nDestination Airport: %s \nDestination Airport Count:%i \nTime: %d \n\n", &flightInfo[i].FlightNum, &flightInfo[i].OriginAirportCode, &flightInfo[i].DestAirportCode, codeInst, timestamp); // print the flightRec structs in form of member columns
}
}
fclose(inFile);
system("pause");
}
Build Messages:
||=== Build: Debug in Project6 (compiler: GNU GCC Compiler) ===|
In function 'codeInst':|
|28|warning: assignment makes integer from pointer without a cast [enabled by default]|
|30|warning: assignment makes integer from pointer without a cast [enabled by default]|
||In function 'main':|
|70|warning: passing argument 1 of 'localtime' makes pointer from integer without a cast [enabled by default]|
|121|note: expected 'const time_t *' but argument is of type 'int'|
|71|warning: return makes integer from pointer without a cast [enabled by default]|
|74|error: expected declaration specifiers or '...' before 'flightInfo'|
|76|warning: format '%s' expects argument of type 'char *', but argument 2 has type 'char (*)[7]' [-Wformat]|
|76|warning: format '%s' expects argument of type 'char *', but argument 3 has type 'char (*)[5]' [-Wformat]|
|76|warning: format '%s' expects argument of type 'char *', but argument 4 has type 'char (*)[5]' [-Wformat]|
|76|warning: format '%d' expects argument of type 'int', but argument 6 has type 'struct tm *' [-Wformat]|
83|warning: control reaches end of non-void function [-Wreturn-type]|
c||In function 'codeInst':|
|43|warning: control reaches end of non-void function [-Wreturn-type]|
||=== Build failed: 1 error(s), 10 warning(s) (0 minute(s), 0 second(s)) ===|
You have initially a function called codeInst, after that, in your main function, you declared a integer variable called codeInst, in line 73 you coded a statement that I really don't know what you want to do (int codeInst(flightInfo);).I assume that you want to call the function int codeInst and for that you must:
change the name of the variable like codeInstVarible
assign to codeInstVarible the function codeInstVarible = codeInst()
and fill all existing parameters in the function in case: (int count, int i, char currCode, char nextCode, flightRec flightInfo[1000])
Check out for info:
[c function localtime()][1]
For the error: |121|note: expected 'const time_t *' but argument is of type 'int'|
In your localtime(flightInfo[i].timestamp),
flightInfo[i].timestamp is an int, not a const time_t *(a pointer to a time_t).
For your int codeInst(flightInfo); function, it should have a return type.
In your main function, you wrote
int codeInst(flightInfo);
Which is incorrect. Look at BarbarianSpock's response.

Initialisation from incompatible pointer type and arrays of structs

I'm learning C at the moment and having a bit of trouble getting my head around pointers and arrays of structs. Here's a simple program I've written:
#include <stdio.h>
typedef struct { /* Define the structure Pokemon that contains a nickname, type and level*/
char nickname[11];
char type[11];
int level;
} Pokemon;
int main(void) {
char nickname[11];
char type[11];
int level;
for (int i = 0; i < 3; i++) { /* Iterate through the loop three times, each time create a new pokemon */
printf("Pokemon %i \n", i);
printf("Nickname: ");
scanf("%s", &nickname);
printf("Type: ");
scanf("%s", &type);
printf("Level: ");
scanf("%i", &level);
Pokemon * poke = {nickname, type, level}; /* Insert the pokemon into the array of Pokemon */
printf("%s, %s, %i", poke->nickname, poke->type, poke->level);
}
}
Basically I want to create a struct for a pokemon that takes the three characteristics. In the main function I want the user to input the characteristics of 3 pokemon and then create an instance of the struct pokemon with these three characteristics and print out these characteristics to stdout. With this code, it compiles but I'm getting the warnings:
pokemon.c:33:9: warning: initialization from incompatible pointer type [enabled by default]
pokemon.c:33:9: warning: (near initialization for ‘poke’) [enabled by default]
pokemon.c:33:9: warning: excess elements in scalar initializer [enabled by default]
pokemon.c:33:9: warning: (near initialization for ‘poke’) [enabled by default]
pokemon.c:33:9: warning: excess elements in scalar initializer [enabled by default]
pokemon.c:33:9: warning: (near initialization for ‘poke’) [enabled by default]
Not sure why this is - I imagine it's something to do with the pointers I've set up, but as I say, still trying to get my head around it.
I'd also like to put each instance of pokemon into an array of three pokemon. So far I've got this:
Pokemon p [3];
// This bit inside the for loop and after the 'poke' struct instantiation
p[i] = poke;
printf("%s,%s,%i inserted\n", poke.nickname, poke.type, poke.level );
But that doesn't want to compile - I imagine it's another pointer error.
Pokemon p[3];
...
Pokemon poke;
strncpy(poke.nickname, nickname, sizeof(poke.nickname));
strncpy(poke.type, type, sizeof(poke.type));
poke.level = level;
p[i] = poke;
Edit: fixed temporary struct init.
Given the description of the desired functionality I'd say there is no need in pointers at all.
Just read the data and store it directly into your array:
int main(void)
{
Pokemon p[3];
for (int i = 0; i < 3; i++)
{
printf("Pokemon %i \n", i);
printf("Nickname: ");
scanf("%s", &(p[i].nickname));
printf("Type: ");
scanf("%s", &(p[i].type));
printf("Level: ");
scanf("%i", &(p[i].level));
printf("%s, %s, %i", p[i].nickname, p[i].type, p[i].level);
}
return 0;
}
Why not directly read into your array?
#include <stdio.h>
typedef struct { /* Define the structure Pokemon that contains a nickname, type and level*/
char nickname[11];
char type[11];
int level;
} Pokemon;
int main(void)
{
Pokemon p[3];
for (int i = 0; i < 3; i++) /* Iterate three times, each time create pokemon */
{
printf("Pokemon %i \n", i);
printf("Nickname: ");
scanf("%10s", p[i].nickname);
printf("\nType: ");
scanf("%10s", p[i].type);
printf("\nLevel: ");
scanf("%i", &p[i].level);
printf("\n%s, %s, %i\n", p[i].nickname, p[i].type, p[i].level);
}
}
In this line:
Pokemon * poke = {nickname, type, level};
You're only declaring a pointer, so you can't initialise it as a struct. And since your struct has character arrays, you can't assign a string pointer.
If you're using C99 you can use a compound literal:
Pokemon * poke = &(Pokemon){.level = level};
Otherwise you'll need to declare a structure, and then assign its address instead.
For the next section, you need
p[i] = *poke;
To copy the structure pointed to into a new one.
However, initialising this way won't copy the strings into the struct. What you can do instead:
strcpy(p[i].nickname, nickname);
strcpy(p[i].type, type);
You should also remove the & in these lines:
scanf("%s", &nickname);
scanf("%s", &type);
The problem is with the line
Pokemon * poke = {nickname, type, level}; /* Insert the pokemon into the array of Pokemon */
So, instead of initializing like that,
you also can simply use this:
Pokemon *poke = malloc(sizeof(Pokemon));
strcpy(poke->nickname,nickname);
strcpy(poke->type,type);
poke->level=level;

not sure what's going on in this code

I have some C code, and I'm not quite sure what's going on.
#include <stdio.h>
#include <stdlib.h>
#define DIM1 7
#define DIM2 5
#define RES_SIZE 1000
typedef double stackElementT;
typedef struct {
stackElementT *contents;
int maxSize;
int top;
int min2;
} stackT;
void StackInit(stackT *stackP, int maxSize) {
stackElementT *newContents;
newContents = (stackElementT *)malloc(sizeof(stackElementT)*maxSize);
if (newContents == NULL) {
fprintf(stderr, "Not enough memory.\n");
exit(1);
}
stackP->contents = newContents;
stackP->maxSize = maxSize;
stackP->top = -1;
}
void StackDestroy(stackT *stackP) {
free(stackP->contents);
stackP->contents = NULL;
stackP->maxSize = 0;
stackP->top = -1;
}
int StackIsEmpty(stackT *stackP) { return stackP->top < 0; }
int StackIsFull(stackT *stackP) { return stackP->top >= stackP->maxSize-1; }
void StackPush(stackT *stackP, stackElementT element) {
if(StackIsFull(stackP)) {
fprintf(stderr, "Can't push element: stack is full.\n");
exit(1);
}
stackP->contents[++stackP->top] = element;
}
stackElementT StackPop(stackT *stackP) {
if(StackIsEmpty(stackP)) {
fprintf(stderr, "Can't pop element: stack is empty.\n");
exit(1);
}
return stackP->contents[stackP->top--];
}
int shell(char* s1, int arg) {
printf("> ");
scanf("%s %d%*c", &s1, &arg);
return arg;
}
int main() {
char cmds[DIM1][DIM2] = {{"push"}, {"pop"}, {"add"}, {"ifeq"}, {"jump"}, {"print"}, {"dup"}};
char* s1; int arg;
arg = shell(s1, arg);
printf("%s\n", &s1);
}
Input: push 4. It prints J+ instead of "push" but prints 4 normally.
It also gives these warnings on compile:
stack.c: In function ‘shell’:
stack.c:60: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘char **’
stack.c: In function ‘main’:
stack.c:71: warning: format ‘%s’ expects type ‘char *’, but argument 2 has type ‘char **’
stack.c:65: warning: unused variable ‘cmds’
stack.c:69: warning: ‘arg’ is used uninitialized in this function
Can someone please explain?
When you use the %s format specifier, it expect a value which is a pointer to the start of a string. In C, this type is char *.
Taking your main function, your variable s1 is of type char *. Therefore, s1 is a valid parameter to printf, so this line is valid:
printf("%s\n", s1);
Note the absence of an & in front of s1. In your code, you used the &, which takes the address of s1, the result of which will be of type char **. This is the wrong type, so don't use the &.
The thing is, printf can't actually tell what type its arguments are, since it is a variadic function. It simply uses whatever arguments are there, according to the types specified in the format string.
The same thing goes for scanf, but there is a pitfall: you must make sure that enough memory is allocated to account for the user input, else you will experience a buffer overflow with unpredictable results. Aside from this, printf and scanf are perfectly complementary.
Anyhoo, this takes care of the compiler warnings, aside from the unused cmds variable (it's unnecessary in the provided code). Also, there is the part of args - it really should be a variable declared inside of shell, and not passed as a parameter, since its value is not even used inside shell.
Don't know what's up with the rest of the code. It's superfluous considering your main function only calls on shell.

Resources