Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 3 years ago.
Improve this question
I'm learning C language and using VBCC as compiler with C99 standard. Trying to figure out how to print multi character elements from array, but printf warn me the type of argument is not matching. It's "just" a warning but i want to understand what i'm doing wrong. Here is the code:
#include <stdio.h>
int main(int argc, char const *argv[]) {
const char* s[] = {"aa","hey","2","1","111","\0"};
int a = 0;
do {
printf("%p\n",&s[a]);
a = a + 1;
} while (s[a] != '\0');
return 0;
}
It's "just" a warning
Well, yes, the compiler may only emit a warning, but it doesn't mean that what you are doing is not an error. Indeed, most of the time it is. As a novice C programmer, you should basically always treat warnings as errors.
What you're doing here:
const char* s[] = {"aa","hey","2","1","111","\0"};
Is declaring an array of char* (char pointers), and assigning to each of the pointers in the array the address of a valid string (provided in the initializer {...}).
This is the same as doing:
const char *s[6];
s[0] = "aa";
s[1] = "hey";
// ... and so on
Each of the strings will be automatically NUL-terminated with the \0 terminator, which is implicit when using the syntax "string literal". The last string that you are adding is unnecessary and empty, and it also contains two terminators, the one you explicitly add and the one implicitly added by default.
Now, to the errors. What you are doing here:
printf("%p\n", &s[a]);
Is incorrect. If you want to print the a-th string, you already have a pointer to it in s[a], so you don't need to take the address (&) again. Another error is using the %p format specifier (I assume you changed it because the compiler told you so), which is not for strings, but for generic pointers (in this case is correct since &s[a] is actually a pointer, but remember that you want to print a string). In the end the above line compiles fine, but it's not what you want. The correct syntax is:
printf("%s\n", s[a]);
The real error in your code is here:
while (s[a] != '\0');
Here, you are comparing a string with a char literal (namely the terminator). You cannot do this, since the two types are different. If you want to terminate your array with a correct value that can then be compared, you can use NULL, since it's an array of pointers (char*).
Another logical error is that you are using a do {...} while cycle, and checking if you reached the end only after printing. In the specific case of your program (with an array of 6 strings) nothing bad happens, but if your array is empty (e.g. char *s[] = {NULL};) you will try to print the first element anyway, which is an error.
Here's the code with the corrections applied:
#include <stdio.h>
int main(int argc, char const *argv[]) {
const char* s[] = {"aa", "hey", "2", "1", "111", NULL};
int a = 0;
while (s[a] != NULL) {
printf("%s\n", s[a]);
a = a + 1;
};
return 0;
}
All strings in C end with zero. You have a table of pointers here and as a marker you should use NULL.
https://godbolt.org/z/KJCdsi
#include <stdio.h>
int main(int argc, char const *argv[]) {
const char* s[] = {"aa","hey","2","1","111", NULL};
int a = 0;
do {
printf("s[%d] = %s\n", a, s[a]);
a = a + 1;
} while (s[a]);
return 0;
}
Use the "%s" format specifier for printing strings, and remove the & reference operator.
printf("%s\n",s[a]);
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
No matter what I try I get an error. I'll remove the pointer, remove the malloc, I've tried reading in the user input in dfferent ways. I come form a java background and very confused on why none of this is working. Also I am not trying to return an array of strings i am just trying to return a string or a single array of chars in c
main(){
char *c = getResources();
}
char * getResources(){
char *str = (char *) malloc(sizeof(char) * 3);
fgets(str, sizeof(str), stdin); /* read in a line */
return *str;
}
There are many errors in your code.
The first one is the return value of the getResources() function. You are returning the value pointed by (*str), which is a single char, but you want to return the whole array.
To fix it you should write return str.
The second one is in the sizeof() operator, which is a compile-time operator. Since it is executed on compile time, it doesn't now the size of the char array malloc-ed at runtime, but only the size of the pointer itself.
Therefore you can't use it this way, but you have to replace it with the actual size of the array.
The third one is in the functions order. You can't use a function that wasn't previously declared. You can either move the full function above the main() or you can just declare it above the main() and leave the implementation behind it.
Finally, the main() function should return an integer.
Bonus tip: don't forget to free the malloc-ed pointer when you don't need it anymore
The fixed code may be as follow:
char * getResources(){
size_t str_size = 3;
char *str = malloc(str_size);
fgets(str, str_size, stdin); /* read in a line */
return str;
}
int main(){
char *c = getResources();
/* do something with c */
free(c);
return 0;
}
Your problem here is that you are returning *str instead of the pointer str:
return str;
Also, you are reading sizeof(str) characters, which is the size of a pointer, that can vary across platforms.
So instead, you need to change that to 3, the number of characters allocated for str:
fgets(str, 3, stdin);
This solution is probably among the worst pieces of C code out there, but it compiles without a warning. Please definitely make sure to read all comments made on your answer, and the info given in the answer by medalib and Andrea.
My code merely condenses all that into a chunk of stuff you can copy paste...
#include <stdlib.h>
#include <stdio.h>
// define it before you use it; a prototype would also have worked
char* getResources(){
char *str = (char *) malloc(sizeof(char) * 3);
// second param is size of input to be expected;
// you passed it the size of a pointer, which is most
// definitely not what you want
fgets(str, 3, stdin); /* read in a line */
// return the pointer; str is already declared as a pointer,
// a further * will only de-reference that again
return str;
}
int main(){
char *c = getResources();
printf("%s\n", c);
return 0;
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I have this code:
char** SplitToWords(char* str);
int main()
{
char** wordarr;
char str[] = "This is a sentence";
wordarr = SplitToWords(str);
return 0;
}
After the main comes the function implementation.
I am not sure the following does what I want it to do (i.e. receive an array of strings from a function):
wordarr = SplitToWords(str);
I somehow managed to convince the compiler that it's ok, but I assume it just does something else.
If it does, how do I find out the length of the array (the number of strings in it).
Thanks
I'll try to quickly visit all aspects you might not yet fully understand:
A string in C is described as a contiguous sequence of chars, ending with a char of value 0 (as a literal: '\0'). It is not a first class object, therefore hasn't its own type. So what you use to hold a string is an array of char. Therefore, taking your question by the word, "receive an array of strings from a function" is not possible.
An array is a contiguous sequence of objects of the same type. In C, the identifier of an array doesn't have a value itself; when it's evaluated, it decays as a pointer to the array's first element instead. This is especially important when passing arrays to functions or returning them from functions -- you can't actually pass the array, you always pass a pointer
e.g. you could write:
char x[] = "foo"; // initialize a char array from a string literal
char *xp = x; // here, x evaluates as a pointer to the first element of the array
You already use pointer types for your function's argument and return value, I just think it's quite important to understand what happens entirely.
You write char** SplitToWords(char* str); and ask whether this returns an "array of strings" -- well, sort of, as you should understand after reading 1. and 2. -- What it does is returning a pointer to char *. This pointer could be a pointer to the first element of an array. So in this case, it would return a pointer to an array of char * pointers. Each of these pointers could itself be a pointer to an array of chars, therefore point to a string. But what's very important is to understand you never return an array, you always return a pointer to it. It's so important because:
You might get the idea to do something like this:
char** SplitToWords(char* str)
{
char *words[16];
// code to fill `words` with pointers to the actual words
return words; // WRONG!
}
Here, because you're not returning the array words but a pointer to it (see point 2), you return a pointer to an object that no longer exists. words is in the scope of your function and has automatic storage duration, that means it only lives as long as the execution is inside of the function. One solution would be to declare words with the static storage class specifier. This way, it lives for the entire execution time of the program. But be aware that this also means there's only a single instance ever, it's always the same object. This will be a major headache for threaded programs, for example. The other way around is to dynamically allocate words using malloc(). But then, the caller of the function must free() it later.
As for your second question, how to let the caller know the number of words -- it's in the comments already, but just for completeness, a typical approach to solve this is to append another entry that is a NULL pointer. So the caller can iterate over the pointers until it finds NULL.
Regarding your comment, of course you can create the array outside the function and pass a pointer to the function, so the function only fills it. This is a common idiom in C (e.g. think about fgets(), which takes a pointer to the char array that's filled with a string by the function).
Functions working this way will need an additional size_t parameter, so they know the size of the array they should fill through the pointer, otherwise you'd have the risk of buffer overflows (this is why gets() was finally removed from the C standard). If you decide that the caller provides the storage, your function should have this prototype:
// returns the number of words found, up to `nwords`
size_t SplitToTwords(char **words, size_t nwords, char *str);
It should be called e.g. like this:
char *words[16];
size_t nwords = SplitToWords(words, 16, "the quick brown fox"); // returns 4
Remember that the strings holding the words themselves need storage as well. You can either manipulate the bytes in str to insert a '\0' after each word, overwriting the first whitespace character (this is what strtok() does) or you can copy the words to new strings, but then you would have to malloc() each of them again and the caller has to free() them later.
Yes, you could solve it by using a function with return value char **. However, there's no way to find out how many words there are afterwards.
You can solve this by allocating one more element for the return pointer and set it to NULL. Then you can get the number of words with this code:
wordarr = SplitToWords(str);
char **ptr=wordarr;
int noWords=0;
while(!*(ptr+noWords))
noWords++;
But if you want to return multiple data in C, you either need to define a return struct or using return arguments. In this case, it could look like this for the first option:
typedef struct wordList {
char **wordarr;
int noWords;
}
wordList SplitToWords(char* str);
And the second:
char** SplitToWords(char* str, int *noWords);
or
void SplitToWords(char* str, char*** wordarr, int *noWords);
Note that there's three *. That's because we want it to be a pointer to char **
#include "stdafx.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXSTRINGS 5000
int main(int argc, char *argv[]) {
char *stringTable[MAXSTRINGS];
char sentence[] = "This is a sentence";
char *token = NULL;
int i = 0;
while ((token = strtok(token == NULL ? sentence : NULL, " ")) != NULL)
{
printf("%s\n\r", token);
stringTable[i] = (char *)malloc(strlen(token) + 1); //have no "plain" C compiler - VS C++ used so cast needed :)
strcpy(stringTable[i++], token);
}
stringTable[i] = NULL; // if you need to iterate through later
printf("%d tokens found\n\r", i);
for (int y = 0; y < i; y++)
free(stringTable[y]);
}
This question already has an answer here:
Declaring and modifying strings in C
(1 answer)
Closed 7 years ago.
I am quite new to C and I come from a Java background.
So, I wanted to declare a String and immediately tried this:
String text;
Then it tells me that the term "String" is not defined.
I searched trough the internet and found this:
char text[16] = { 'E','i','n',' ','l','a','n','g','e','r',' ','T','e','x','t','\0' };
But this isn't very nice and too much work. There must be an other, better method.
Maybe with importing something. Does anyone has a good solution to this?
There is no string type in C.
A string variable is a 1-d array of ASCII characters terminated by a null character.
The method you tried to declare a string is right.
char text[16] = { 'E','i','n',' ','l','a','n','g','e','r',' ','T','e','x','t','\0' };
But the easy one is to simply
char str[]="Ein Langer Text"
This is initialization is same as previous one but in this case compiler automatically inserts the null character at the end.
A simple example:
#include <stdio.h>
int main(int argc, char const *argv[])
{
char str[]="Ein Langer Text";
int i;
for (i = 0; str[i]!='\0' ; ++i)
{
printf("%c",str[i]);
}
printf("\n");
return 0;
}
You can even have a limited size string such as:
char[40]="whatever you want to keep here up to fourty characters";
In C, there is no standard data type called String. It is either a string literal or a char array.
FWIW,
char text[16] = { 'E','i','n',' ','l','a','n','g','e','r',' ','T','e','x','t','\0' };
can be shortened as
char text[ ] = { "Ein langer Text"}; //modifiable, but size limited to
// the initalizer
or
char text[128] = { "Ein langer Text"}; // modifiable, with larger size than initializer
or
char *text = "Ein langer Text"; //not modifiable
It's even simpler:
char text[]="test 123";
or
char text[9]="test 123";
in c, there is no string type:
in c you can try :
char *mystring = "Hello world";
i c++ you can try:
#include <iostream>
std::string mystring = "Hello";
This question already has answers here:
returning a local variable from function in C [duplicate]
(4 answers)
Closed 7 years ago.
I am quite new to C and I am playing with some string operations. I have encountered quite a strange problem for me while returning a string from a function. My simple program is as follows:
int main(int argc, char* argv[])
{
char text[] = "abAB";
char* out = testString(text);
printf("Result Text: %s", out);
printf("\n");
}
char* testString(char* input) {
char* text = copyString(input);
return text;
}
The copyString function defines a simple operation to copy one string to another. It is as follows:
char* copyString(char* input) {
char output[100];
int index = 0;
while (input[index] != '\0') {
output[index] = input[index];
index++;
}
output[index] = '\0';
return output;
}
The problem is that while I am debugging the application, the string I am returning from a function seems to be OK (Visual Studio visualises it well enough) and when the printf line occurs, the string outputted on the stdout is something completely strange and unfamiliar - a smily face. Sadly, I can't post images yet in order to show you what I see in my console as output.
I am using Visual C++ Express 2010 as an IDE if this could be helpful.
You are returning a variable declared within a function, which will cease to exist outside the scope in which it is declared. Use a dynamically allocated char array and then return a pointer to it.
char* output = malloc(100 * sizeof(char));
...
return output ;
Note : You are assuming that input string is less than 100 characters. Instead of that, try passing the length of string as a parameter or use strlen. Your program will crash if input string has more than 99 characters.
Also as noted in comments, free the memory allocated when you are done using it.
I've seen a lot of questions on that on StackOverflow, but reading the answers did not clear that up for me, probably because I'm a total newbie in C programming. Here's the code:
#include <stdio.h>
char* squeeze(char s[], char c);
main()
{
printf("%s", squeeze("hello", 'o'));
}
char* squeeze(char s[], char c)
{
int i, j;
for(i = j = 0; s[i] != '\0'; i++)
if(s[i] != c)
s[j++] = s[i];
s[j] = '\0';
return s;
}
It compiles and I get segmentation fault when I run it. I've read this faq about about returning arrays and tried the 'static' technique that is suggested there, but still could not get the program working. Could anyone point out exactly what's wrong with it and what should I be paying attention in the future?
The 1st argument passed to the squeeze function is a read-only string literal "hello", which you are trying to modify.
Instead pass it a modifiable char array:
char str[] = "hello";
printf("%s", squeeze(str, 'o'));
The problem is that the constant char array "hello" may not correctly be modified by the function to which it was passed. So, just make sure you're passing a non-constant array (for example by making a local array to be passed, as long as the result is not needed outside of squeeze's caller):
int main()
{
char xxx[] = "hello";
printf("%s", squeeze(xxx, 'o'));
return 0;
}
You'd expect that such a constant could only be passed to a const argument (so that the compiler itself could tell you what you're doing wrong), but, alas, that's not what the C standard mandates (presumably for reasons of backwards compatibility with historical code).
This is trying to modify non-modifiable data.
"hello" is a constant string, stored in memory somewhere. What you're trying to do, then, is change it, and that's generally not allowed. I don't see what you mean by "static", but what you want would be something like...
int main()
{
char hello_str[16];
strcpy(hello_str, "hello");
printf("%s", squeeze(hello_str, 'o'));
}