Error in initializing array in C - c

Below is my code:
#include <stdio.h>
#include <stdlib.h>
typedef int index_key;
typedef char text_t;
text_t *create_text()
{
//text_t text[SIZ];
text_t *c;
text_t text[]="fl";
c= text;
return c;
}
int main()
{
text_t * create();
return 0;
}
I get an error - expected expression before ‘]’ token. Why is this error occuring? Isn't text[] a global declaration and I can access it anywhere? What is wrong in this program and how should I correct it.

You cannot have an array definition like
text_t text[];
Either specify the size,
#define SIZ 256 //arbitary value
text_t text[SIZ];
or use initializer.
text_t text[] = {`A`, `B`, `C`};
EDIT:
As per the latest addition, please be informed that "sldk" (as you've iused) and {'s', 'd', 'l', 'k'} (as i've suggested) are not the same. The former is a string literal while the later being initalizer list of chars. You can use the second in your case, not the first one.
EDIT 2
That said, your create_text() function is wrong. Effectively, you're returning the address of a local variable text. Incorrect. Will invoke UB.

I see the following problems:
text_t text[];
is a declaration, not a definition. You have to add a line that defines text, such as:
text_t text[100];
The line
text[]="sldk";
is wrong on two accounts.
You cannot assign to an array using the = operator.
You cannot use text[] to access the array.
Here's a fixed version of your program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef int index_key;
typedef char text_t;
// This is a forward declaration of the array.
text_t text[];
text_t *create()
{
text_t *c;
// One way to get some string into a char array.
strcpy(text,"sldk");
c = text;
return c;
}
// This is the definition of the array.
text_t text[100];
int main()
{
text_t * create();
return 0;
}
Update
Regarding your updated create_text function...
It should work since string literals are stored in read-only memory of the program. It will lead to problems as soon as you try to change anything in it. It's better to use a safer approach, such as:
text_t *create_text()
{
text_t *c = malloc(20);
strcpy(c, "fl");
return c;
}

The C language does not have a built in string data type unlike C++, Java or C#.
The strings are represented as arrays of characters in C. So any array in C should have some size.
int numbers[10];
char string[50];
The C function which operate on these types of strings ( like strlen which calculates the length of the strings expects a 'null' or '\0' character at the end of the array.
Initializing a character array with string literal like "test" will automatically insert a null character at the end.
char str[10] = "test";
characters stored {'t','e','s','t','\0'}
If you are initializing it with comma separated characters, you need to explicitly specify this character.
char str[10] = {'t','e','s','t', '\0'}; //explicit null character
So, generally the array size is one more than the maximum size of the string you want to store. So it is quite common to see declaration like the following.
char name[MAXLEN+1];
If you are using C++, you can use a build-in data type called string.
string str;
Hope this helps

Related

Store char variables in other char variables in C

I am trying to do the following, create a multy-charr array with other char variables.
char data_info_1[] = "Wellcome.";
char data_info_2[] = "Please";
char data_info_3[] = "If";
int size_line= sizeof(data_info_1)/sizeof(data_info_1[0]);
char data_info[3][size_line]={{data_info_1},{data_info_2},{data_info_3}};
One solution would be the following one, but I am not interested in just putting the string right in the data_info variable
char data_info[3][size_line]={{"Wellcome"},{"Please"},{"If"}};
Could you please explain me why the first thing that I have writen is not valid. And if there is a solution to my problem.
Thanks.
To answer your question, neither of your solutions is correct, you can't initialize a 2D array of chars like that.
The second option would be valid if it wasn't a variable sized array, i.e.
char data_info[3][10]={"Wellcome", "Please" ,"If"};
^
Valid -> fixed size
Assignments like those would be possibe if you had an array of pointers:
char *data_info[] = {data_info_1, data_info_2, data_info_3}; //1
Or
const char *data_info[] = {"Wellcome", "Please", "If"}; //2
But these may not be what you need.
Option 1 will contain pointers to the original strings, any changes made to them through those pointers will be reflected in the original strings.
Option 2, the pointers are being initialized with string literals and those can't be changed, that's why I added the const qualifier as a metter of safety.
If neither of these constrains work for you, you'll need to copy the strings with something like strcpy, strncpy or better yet memcpy:
#include <string.h>
//...
memcpy(data_info[0], data_info_1, sizeof data_info_1);
memcpy(data_info[1], data_info_2, sizeof data_info_2);
memcpy(data_info[2], data_info_3, sizeof data_info_3);
Arrays may not be initialized by arrays. You may initialize a character array with string literals as you did in this declaration
char data_info[3][size_line]={{"Wellcome"},{"Please"},{"If"}};
Relative to your case you could declare an array of pointers to char like for example
char * data_info[] = { data_info_1, data_info2, data_info3 };
Some remarks:
you do not need to divide by sizeof char becuse it is by definition 1
You can only use constant expressions when defining or initializing global variables char data_info[3][sizeof(data_info_1)];
To "store" one char array in other you need to copy it. Initialization will not work as you cannot assign the arrays.
#include <string.h>
char data_info_1[] = "Wellcome.";
char data_info_2[] = "Please";
char data_info_3[] = "If";
char data_info[3][sizeof(data_info_1)];
void foo(void)
{
strcpy(data_info[0], data_info_1);
strcpy(data_info[1], data_info_2);
strcpy(data_info[2], data_info_3);
}
only structs or unions can be assigned. So you can wrap array into the struct and the assignment or initializations will copy the whole array.
struct stringWR
{
char str[50];
};
struct stringWR data_info_1 = {"Wellcome."};
struct stringWR data_info_2 = {"Please"};
struct stringWR data_info_3 = {"If"};
struct stringWR data_info[3];
void foo(void)
{
data_info[0] = data_info_1;
data_info[1] = data_info_1;
data_info[2] = data_info_1;
}
void bar(void)
{
struct stringWR data_info[3] = {data_info_1, data_info_2, data_info_2};
}

how to scan strings with white spaces and print them C

I have to read a string, to concatenate with another and print the result
I tried this code:
int main(){
char s= "StackOverflow ";
char ss[100];
fgets(ss,100,stdin);
// i know i can use strcat but i don't want it here
printf("%s%s",s,ss);
return 0;
}
the ss is "is the best site for learning things!"
Some help?
First of all, you have to make your program compilable, as compilation gives some errors.
1.) s must be defined as char *s or char s[] because char s only allows one character to be stored there, and not an array. char *s declares a pointer to the string literal and char s[] declares an array of characters of as many as present in the string literal and initializes it with the characters of the specified string literal.
2.) stdin is a global variable of type FILE * (actually it isn't but it behaves as) that represent the standard input. If you don't declare it, the compiler doesn't know where the stdin identifier came from, so it issues an error. The way to eliminate this second error is to #include <stdio.h> which has a definition for it and makes the compiler happy.
Once you do these two steps, your program is:
#include <stdio.h>
int main(){
char s[]= "StackOverflow ";
char ss[100];
fgets(ss,100,stdin);
// i know i can use strcat but i don't want it here
printf("%s%s",s,ss);
return 0;
}
and behaves as you wanted.

Adding a null terminator to a string

I have used sscanf to scan in a string and add it to a structure. The only problem is that I cannot print out the string because there is no null terminator added by default. I tried to add a null in there with the strcat() function but came to the realization this cannot work. Thanks for any help.
struct a
{
int *ref;
char string[50];
}rec;
void task()
{
char *p_test;
char test[50] = "9999:STRING OF TEXT";
p_test = test;
sscanf(p_test, "%d:%[^\n]", &rec.ref, rec.string);
printf("String is:%s", &rec.string);
}
There are multiple problems with your code.
test[50] = "9999:STRING OF TEXT";
This is wrong for two reasons.
A) test is an array of char, not an array of char*. So, when you assign a string (a char*) to an element, the address is converted to a char.
B) Element 50 does not exist in your array, and writing to it invokes undefined behavior. You have an array of 50 elements with indices 0...49.
To assign an initial value to your array, all you need do is:
char test[50] = "9999:STRING OF TEXT";
And since test does not need to be modified...
const char *test = "9999:STRING OF TEXT";
If you want to zero an array, the simplest method is:
char test[50] = {0};
Of course, you don't need to if you assign the string properly to begin with, and this is not your problem.
Your string member of the a struct is a char, not a char* (a string), and using the %s format specifier when printing it invokes undefined behavior.
main is defined to return int, not void.
sscanf expects pointers to data to fill in. rec.ref is an int, you need to pass its address, i.e., &rec.ref.
You need to allocate storage for rec.string.
Here is a working example:
#include <stdio.h>
#define STRING_LEN 50
struct a
{
int ref;
char string[STRING_LEN];
} rec;
int main()
{
char test[STRING_LEN] = "9999:STRING OF TEXT";
// note that, in the real world, this may
// be a buffer overflow waiting to happen
sscanf(test, "%d:%[^\n]", &rec.ref, rec.string);
printf("String is:%s, rec is:%d", rec.string, rec.ref);
return 0;
}
You have a number of problems; a lack of null-terminator actually isn't one of them.
One problem is a syntax error; this:
char test[50]
test[50] = "9999:STRING OF TEXT";
is not valid syntax. You need:
char test[50] = "9999:STRING OF TEXT";
Another problem is that rec doesn't have a string (a char * or char[]), it just has a single character (a char). A simple approach, to get you started, is:
struct a
{
int ref;
char string[50];
} rec;
A third problem is that sscanf's arguments all have to be pointers. C is a pass-by-value language; if you just pass in an integer, that doesn't give sscanf any way to modify that integer:
sscanf(test, "%d:%[\n]", &rec.ref, rec.string); // (once rec.string is a pointer)
A fourth problem is that the format-specifier %[\n] does not mean what you seem to want it to mean. (Maybe you actually wanted %[^\n]?)
Other, smaller issues include your return-type for main (it should be int, not void).
The common thread with most of these issues is that your compiler would have eagerly helped you identify them, had you simply turned on compiler warnings!

How to convert char pointer into char in C Open VMS

This is to convert from char pointer into char.
I followed the codes from another topic but it seems like it's not working to me.
I am using Open VMS Ansi C compiler for this. I don't know what's the difference with
another Platform.
main(){
char * field = "value1";
char c[100] = (char )field;
printf("c value is %s",&c);
}
the output of this is
c value is
which is unexpected for me I am expecting
c value is value1
hope you can help me.
strcpy(c, field);
You must be sure c has room for all the characters in field, including the NUL-terminator. It does in this case, but in general, you will need an if check.
EDIT: In C, you can not return an array from a function. If you need to allocate storage, but don't know the length, use malloc. E.g.:
size_t size = strlen(field) + 1; // If you don't know the source size.
char *c = malloc(size);
Then, use the same strcpy call as before.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char * field = "value";
char c[100]="";
strncpy(c,field,100);
printf("c value is %s",c);
return 0;
}
In C, the char type holds a single character, not a string. char c[100]; doesn't allocate a char of length 100, it allocates an array of 100 consecutive chars, each one byte long, and that array can hold a string.
So what you seem to want to do is to fill an array of chars with the same char values that are at the location pointed at by a char *. To do that, you can use strncpy() or any of several other functions:
strncpy(c,field,100); /* copy up to 100 chars from field to c */
c[99] = '\0'; /* ..and make sure the last char in c is '\0' */
..or use strcpy() since you know the string will fit in c (better in this case):
strcpy(c,field);
..or:
snprintf(c,100,"%s",field);

string literal in c

Why is the following code illegal?
typedef struct{
char a[6];
} point;
int main()
{
point p;
p.a = "onetwo";
}
Does it have anything to do with the size of the literal? or is it just illegal to assign a string literal to a char array after it's declared?
It doesn't have anything to do with the size. You cannot assign a string literal to a char array after its been created - you can use it only at the time of definition.
When you do
char a[] = "something";
it creates an array of enough size (including the terminating null) and copies the string to the array. It is not a good practice to specify the array size when you initialize it with a string literal - you might not account for the null character.
When you do
char a[10];
a = "something";
you're trying to assign to the address of the array, which is illegal.
EDIT: as mentioned in other answers, you can do a strcpy/strncpy, but make sure that the array is initialized with the required length.
strcpy(p.a, "12345");//give space for the \0
You can never assign to arrays after they've been created; this is equally illegal:
int foo[4];
int bar[4];
foo = bar;
You need to use pointers, or assign to an index of the array; this is legal:
p.a[0] = 'o';
If you want to leave it an array in the struct, you can use a function like strcpy:
strncpy(p.a, "onetwo", 6);
(note that the char array needs to be big enough to hold the nul-terminator too, so you probably want to make it char a[7] and change the last argument to strncpy to 7)
Arrays are non modifiable lvalues. So you cannot assign to them. Left side of assignment operator must be an modifiable lvalue.
However you can initialize an array when it is defined.
For example :
char a[] = "Hello World" ;// this is legal
char a[]={'H','e','l','l','o',' ','W','o','r','l','d','\0'};//this is also legal
//but
char a[20];
a = "Hello World" ;// is illegal
However you can use strncpy(a, "Hello World",20);
As other answers have already pointed out, you can only initialise a character array with a string literal, you cannot assign a string literal to a character array. However, structs (even those that contain character arrays) are another kettle of fish.
I would not recommend doing this in an actual program, but this demonstrates that although arrays types cannot be assigned to, structs containing array types can be.
typedef struct
{
char value[100];
} string;
int main()
{
string a = {"hello"};
a = (string){"another string!"}; // overwrite value with a new string
puts(a.value);
string b = {"a NEW string"};
b = a; // override with the value of another "string" struct
puts(b.value); // prints "another string!" again
}
So, in your original example, the following code should compile fine:
typedef struct{
char a[6];
} point;
int main()
{
point p;
// note that only 5 characters + 1 for '\0' will fit in a char[6] array.
p = (point){"onetw"};
}
Note that in order to store the string "onetwo" in your array, it has to be of length [7] and not as written in the question. The extra character is for storing the '\0' terminator.
No strcpy or C99 compund literal is needed. The example in pure ANSI C:
typedef struct{
char a[6];
} point;
int main()
{
point p;
*(point*)p.a = *(point*)"onetwo";
fwrite(p.a,6,1,stdout);fflush(stdout);
return 0;
}

Resources