i have a token of type char* that i want to get the second element of. For example the tokens all consist of a 4 long course number like 1405, i want to grab the 2nd character or 4, and turn it into an interger. I use strcpy to add the string into a char string array in order to grab the 4 but i get some errors and im not quite sure how to fix them. here is my code
#include <stdio.h>
#include <string.h>
int search(struct id array[],char* tok);
int main(void)
{
char* token2 = "1405";
char* text[] = malloc(strlen(token2)+1);
strcpy(text,token2);
int i,number;
for(i=0;i<4;i++)
if(i==1)
{
number = atoi(token2[i]); }
printf("%d\n",number);
i get the following compilation errors
gcc structures_arrayof.c
structures_arrayof.c: In function ‘main’:
structures_arrayof.c:23:20: warning: incompatible implicit declaration of built-in function ‘malloc’ [enabled by default]
char* text[] = malloc(strlen(token2)+1);
^
structures_arrayof.c:23:5: error: invalid initializer
char* text[] = malloc(strlen(token2)+1);
^
structures_arrayof.c:24:5: warning: passing argument 1 of ‘strcpy’ from incompatible pointer type [enabled by default]
strcpy(text,token2);
^
In file included from structures_arrayof.c:5:0:
/usr/include/string.h:129:14: note: expected ‘char * __restrict__’ but argument is of type ‘char **’
extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
atoi is for converting a string to integer. However, you want to convert a single character.
You can write:
number = token2[i] - '0';
This works because the digits '0' through '9' have consecutive character codes. There is no need to malloc or whatever.
To work with what you are doing....
This should clear up the first set of errors.
char* text = malloc(strlen(token2)+1);
You are need a pointer to a char string.
To do the the conversion, you need to null terminate the string.
token2[i+1]=0;
Then you can
number = atoi(token2[i]);
The first error:
You forgot to #include <stdlib.h> to get malloc.
The second error:
A string represented as a pointer to a char, so you just need
char *text = malloc(strlen(token2)+1);
Drop the brackets.
Alternatively, since size is known at compile time, you can declare it without malloc using char text[5];
The third error:
It warns you that you are using the wrong type of pointer. This should be fixed by changing the declaration as mentioned above.
The fourth error (not in your pasted compiler output):
As Matt McNabb pointed out, you should not be using atoi. Replace it with
number = token2[i] - '0'; This will subtract the ASCII vaule of 0, returning the integer value of the character.
An additional comment: I'd recommend changing the spacing/indent style of the if statement. Putting an opening brace on its own line and a closing brace on the same line as the last statement is very non-conventional, and it decreases readability.
I suggest you pick a standard style and try to stick to it. Personally, I like the Linux Kernel Coding Style, but feel free to choose whichever suits you.
Related
#include<stdio.h>
#include<curses.h>
#include<string.h>
void main()
{ const char *str1[20];
const char *str2[20];
int comp;
printf("Enter the first string:\n");
scanf("%s",&str1);
printf("Enter the second string:\n");
scanf("%s",&str2);
comp=strcmp(str1,str2);
}
This was compiled in gcc compiler 4.8 . A detailed explanation will be appreciated.
Error message:
strcmp.c: In function ‘main’:
strcmp.c:10:10: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘const char * (*)[20]’ [-Wformat=]
scanf("%s",&str1);
^
strcmp.c:12:10: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘const char * (*)[20]’ [-Wformat=]
scanf("%s",&str2);
^
strcmp.c:13:14: warning: passing argument 1 of ‘strcmp’ from incompatible pointer type [-Wincompatible-pointer-types]
comp=strcmp(str1,str2);
^~~~
In file included from strcmp.c:3:0:
/usr/include/string.h:140:12: note: expected ‘const char *’ but argument is of type ‘const char **’
extern int strcmp (const char *__s1, const char *__s2)
^~~~~~
strcmp.c:13:19: warning: passing argument 2 of ‘strcmp’ from incompatible pointer type [-Wincompatible-pointer-types]
comp=strcmp(str1,str2);
^~~~
In file included from strcmp.c:3:0:
/usr/include/string.h:140:12: note: expected ‘const char *’ but argument is of type ‘const char **’
extern int strcmp (const char *__s1, const char *__s2)
const char *str1[20];
Should be
char str1[20];
You want a mutable array of characters, not an array of pointers.
scanf("%s",&str1);
Should be:
scanf("%s",str1);
The scanf function needs the address to store the input in. That's equivalent to &str1[0] which is what str1 decays into.
Your declared arrays are of the wrong type and qualifier.
The first thing is the incorrect declarations of the string buffers. You want an array of characters, but const char* str[20] declares an array of const character pointers (that is why the compiler is talking about argument 2 with type const char * (*)[20] being the wrong type). You do not want const here either since you want the characters to be changeable. char str[20] declares a string of characters which is what you really want.
Another point in C coding is that the address of an array is the same as the name of an array, so &str1 and str1 mean the same thing.
Change const char *str1[20]; to char str1[20];,
and scanf("%s",&str1); to scanf("%s",&str1[0]);
Same with second string.
As it currently is, you're declaring, not an array of characters, but an array of pointers to characters.
You're not printing any value, so hard to know the result of the comparison.
You did not explain exactly what your code is supposed to do, but I guess that
const char *str1[20];
(the above declares an array of 20 pointers to constant strings, or zones of several char-s)
should probably be
char str1[256];
this declares a single string -which should be writable by the computer, since you read it from thje user- of at most 256 bytes, and you want it to be null-terminated
(I'm using 256, because 80 bytes is really not a lot - and 20 bytes is not enough -; you want UTF8 everywhere, and 80 bytes can be much less than 80 characters).
BTW
scanf("%s",&str1);
is poor taste (may you wanted scanf("%19s", str1);). I suggest to use fgets and code:
if (!fgets(str1, sizeof(str1)-1, stdin)) {
perror("fgets str1");
exit(EXIT_FAILURE);
}
(Hint, you should always test for successful input).
BTW, always improve your code to get no warnings, and yes you need to compile with gcc -Wall -g (all warnings and debug info) to be able to use the gdb debugger (which you need to learn).
I'm trying to return a pointer to a character array. The function is located in a different file. I compile the files together and it prints out "hello" just fine, but still produces a warning
warning: assignment makes pointer from integer without a cast [enabled by default]
I tried casting the returned value of function() to (char *), but ended up with a different warning:
warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]" instead.
What am I doing wrong?
File 1
#include <stdio.h>
int main()
{
printf("%s\n", function());
return 0;
}
File 2
#include <stdio.h>
char *message = "hello";
char *function()
{
return(message);
}
The problem here is a missing prototype. For historical reasons C lets you use functions without declaring them. However, all such functions are considered returning int, and all their parameters are considered int as well.
Since your function returns char*, you need to add a prototype for it (it's a good idea to have prototypes for all your functions, including ones that indeed return an int):
#include <stdio.h>
char *function(); // <<== Add this line
int main()
{
printf("%s\n", function());
return 0;
}
I'm trying to write my own version of strcat (I call it "append"). Here's what I have:
#include <stdio.h>
int main() {
char *start = "start";
char *add = "add";
append(start, add);
printf(start);
}
void append(char *start, char *add) {
//get to end of start word
char *temp = &start;
while (*temp != '\0') {
temp++;
}
*temp = *add;
while (*temp != '\0') {
*temp = *add;
}
}
When I compile, I get 3 warnings and an error:
1) warning: implicit declaration of function 'append' is invalid in C99
2) warning: format string is not a string literal (potentially insecure)
3) error: conflicting types for 'append'
I don't see how the arguments I pass into my append function within main conflict with the function definition below it.
4) warning: incompatible pointer types initializing 'char *' with an expression of type 'char **'; remove &
Why would I want to remove & here? I thought I could declare and initialize my char pointer to the proper memory address all at once.
Any help is much appreciated.
1) warning: implicit declaration of function 'append' is invalid in C99
and
3) error: conflicting types for 'append'
because, you did not provide a prototype of append() before using it. You need to add a forward declaration of a function before using it. Add
void append(char *start, char *add);
before main() or put the function definition before main()
Next, in case of
char *start = "start";
char *add = "add";
start and add are the pointers to string literals. They are usually placed in read-only memory, means you cannot change the contents. Any attempt to do so will lead to undefined behavior.
Then, regarding
2) warning: format string is not a string literal (potentially insecure)
printf(start);
is wrong usage in this case. You need to use it like
printf("%s\n", start);
Check the man page of printf() for more details.
and finally,
4) warning: incompatible pointer types initializing 'char *' with an expression of type 'char **'; remove &
is because of
char *temp = &start;
you need to use something like
char *temp = start; //start is a char *, no need for & here
Note: The recommended signature of main() is int main(void).
You have multiple problems with that short code. First you have
warning: implicit declaration of function 'append' is invalid in C99
The meaning of this warning is that you need to declare functions before you use them. If you don't declare a function before you use it, the compiler will have to guess its arguments and return type, and often it guesses badly.
Continuing with next warning:
warning: format string is not a string literal (potentially insecure)
This is because you provide a string variable to printf, this is, like the warning tells you, insecure. Think for example about a case where you read input from a user, and use that input as a format string to printf. What would stop the user from adding format codes in the input string? And since you don't pass arguments where would the arguments for those formats come from?
And now the error:
error: conflicting types for 'append'
This is because of the first problem, that the compiler guessed the arguments or return type of the function wrongly.
Now on to another major problem that doesn't show up as compiler errors or warnings, namely undefined behavior.
The problem is that your start and add variables points to string literals. String literal are read only (in fact, a string literal is a pointer to an array of non-modifiable characters). The first problem is that you try to modify the contents of these arrays, the second is that the arrays are only as big as needed and you are writing outside of that memory. Both these problems are causes for undefined behavior.
But this is the easy part, what the compiler could detect.
The worse part is that as you declared start as char *start = "start", it only points to an array of 6 chars (5 letters + terminating null).
So when you try to add add at its end you get Undefined Behaviour (for writing beyond and of an array) ! In that case you are writing memory where any else could be => your program is likely to break or segfault.
C99 is pretty restrictive in how it wants you to declare things.
As Sourav said,
1 & 3 are caused by your append() function is used before it's declared in the file, which causes the compiler to generate an implicit declaration for you. Move the append() function above main() to fix that (or add a function prototype).
4 is caused by this line: char *temp = &start;
temp here is actually a char**, since you're taking the address of a char*
I'm working on a block-cipher program in C, and it seems none of my functions are returning the proper type of pointer, so my code won't even compile.
An example is this:
char *evenString(char * inText) /*takes a string of text. If it has an odd number of chars, it adds ASCII char 19 as padding.*/
{
int inputLength = strlen(inText);
char* evenText; /*pointer to character array*/
if(inputLength%2) /*If even, pad*/
{
evenText = (char*) malloc(sizeof(char) * (inputLength+2));
strcpy(evenText,inText);
evenText[inputLength] = FILLER_CHARACTER;
}
else
{
evenText = (char*) malloc(sizeof(char) * (inputLength+1));
strcpy(evenText,inText);
}
return evenText; /*which should be a char*, right?*/
}
When I call it in main, the call looks like this:
char *plainText = evenString(inputText);
And the compiler brings up these exceptions:
block_cypher.c:28:22: warning: initialization makes pointer from integer without a cast [enabled by default]
char *plainText = evenString(inputText);
block_cypher.c: At top level:
block_cypher.c:38:7: error: conflicting types for ‘evenString’
char *evenString(char * inText)
block_cypher.c:28:22: note: previous implicit declaration of ‘evenString’ was here
char *plainText = evenString(inputText);
block_cypher.c: In function ‘evenString’:
block_cypher.c:45:26: warning: incompatible implicit declaration of built-in function ‘malloc’ [enabled by default]
evenText = (char*) malloc(sizeof(char) * (inputLength+2));
block_cypher.c:53:26: warning: incompatible implicit declaration of built-in function ‘malloc’ [enabled by default]
evenText = (char*) malloc(sizeof(char) * (inputLength+1));
It's like this for all my functions, which all return a pointer of type int* or char*. I haven't even been able to compile, so I don't even know where to begin to fix this. Any insight to this would be greatly appreciated. Thank you for your time!
UPDATE: Thank you all! I followed all your advice:
I inserted function prototypes, which resolved many of the errors right away.
I included ; I don't know what I was thinking, but I've been working in a Java IDE a lot recently and forgot a lot of important stuff about C.
As suggested, I stopped casting malloc(). My C professor told us that since malloc returns a VOID* pointer, it's always good practice to cast it.
Thank you all!
The below error:
block_cypher.c:28:22: note: previous implicit declaration of ‘evenString’ was here
// ^^^^^^^^
char *plainText = evenString(inputText);
indicates that at the location where the evenString function is invoked, the compiler doesn't know that function's signature, which usually means you are missing proper header file. As a result of that, the compiler deduces its own declaration (based on supplied arguments), with return type defaulted to int:
int evenString(char* inText);
And this is where the error originates from:
warning: initialization makes pointer from integer without a cast [enabled by default]
// ^^^^ ^^^^^^^
After reading all errors / warnings it looks that you define the evenString function after its first usage. You should either declare the function before its first usage, or move entire function definition to the top of your translation unit (at least before you use that function for the first time).
That is:
block_cypher.c: At top level:
block_cypher.c:38:7: error: conflicting types for ‘evenString’
// ^^ ^^^^^^^^^^^
char *evenString(char * inText)
block_cypher.c:28:22: note: previous implicit declaration of ‘evenString’ was here
// ^^
char *plainText = evenString(inputText);
means you have invoked evenString(inputText); at line 28, where the compiler deduced the return type to be int, and only then you declare/define the function at line 38, which is too late (at least without previous declaration).
To make it working, try adding declaration before that 28 th line:
char* evenString(char* inText);
You need to add a prototype for evenString() before calling the function.
Without a prototype the compiler assumes it returns a value of type int and the assignment
char *plainText = evenString(inputText);
is like
char *plainText = <int value here>;
so the compiler complains
I'm compiling my work and this error kept on appearing no matter how I edit my code:
expected expression before ‘char’
and
format ‘%s’ expects type ‘char *’, but argument 2 has type ‘int’
as of the second error, I've tried to use typecasting but the problem is really persistent. Does anyone know how to?
This is a part of my code:
while ( char my_wget (char web_address[BUFLEN]) != EOF ) {
printf ("%s", (char) web_address[BUFLEN]);
Because you've got a syntax error where you wrote char and char is not allowed.
Maybe you had in mind:
int ch;
char web_address[BUFLEN];
while ((ch = my_wget(web_address)) != EOF)
printf("%s\n", web_address);
With the correct declaration for my_wget() around (such as extern int my_wget(char *buffer);), that should compile. You can't declare variables everywhere.
The second error is because web_address[BUFLEN] is a character (certainly in my code; it seems to be in yours, too, since the compiler managed to identify the type sufficiently to generate the error). It is also one beyond the end of the array if you declared it as I did. Treating a char value (probably an 8-bit quantity) as an address (pointer; probably a 32-bit or 64-bit quantity) is wrong, which is why the compiler complained.
In the printf() statement, try changing the part char to char*
Same applies to the condition in the while loop. Change the char before web_address to (char*)
I find it weird that you write "char" before my_wget(). Can you please be more specific?
See this code below
#include <stdio.h>
int main()
{
char c;
printf ("%s", st);
}
when i compile it , i get the same warning message.
warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’
so i change the program to
#include <stdio.h>
int main()
{
char *str = "string";
printf ("%s", st);
}
And now the program compiles properly.
So being a newcomer to c , this is how you learn the language , write the smallest example , to prove that you have a firm grip over the concept.