Can't initialize char array to a variable in c - arrays

While using Turbo c++ initializing array of char variable getting error code as follows
int gd=DETECT,gm,i,d=0,x,y;
char s[12]={"3","4","5","6","7","8","9","10","11","12","1","2","\0"};
initgraph(&gd,&gm,"..\\BGI");
but while used to initialize s[12][3], the initializer list works fine!

There is a difference between "3" and '3'.
"3" is a string literal
'3' is a character constant (to nitpick: integer character constant)
here, to initialize an array of char type, you seem to need (brace-enclosed) list of character constants, not strings.
but while using s[12][3] works fine
Well, there you're initializing arrays.
Moral of the story: When in doubt, check the data types!!

You need to change:
char s[12]={"3","4","5","6","7","8","9","10","11","12","1","2","\0"};
to
char s[13]={'3','4','5','6','7','8','9','10','11','12','1','2','\0'};
As char array elements should be char literals not string literals

You are trying to store chars, not strings, so why do you use double quotes?
"a" is a string, 'a' is a character.
What you actually want to store is strings, and for that you need a 2D array, like this:
s[12][3] = {"3","4","5","6","7","8","9","10","11","12","1","2"};
You cannot express 10 as a single character, I mean '10' does not exist. Single characters are from 0 to 9 when it comes to digits. For that reason, you need a string for 10, like this "10".
Now, you need the second dimension of your array to be 3, because the string "10" (for example) is a null-terminated string, thus 2 characters for its actual contents, plus one for the null-terminator, gives as 3.
PS: Turbo-C++ is an ancient compiler. Upgrade to GCC or anything else, really.

Related

char array in a struct data type

I actually have a question regarding the concept of a char array, especially the one which is declared and initialized like below.
char aString[10] = "";
What i was taught was that this array can store up to 10 characters (index 0-9) and that at index 10 there is an automatically placed null terminating character (i know that accessing it would not be right) such that if we use string handling functions (printf, scanf, strcmp, etc.) they would know when the string stops.
However when I tried making a struct data type like below,
typedef struct customer{
char accountNum[10];
char name[100];
char idNum[15];
char address[200];
char dateOfBirth[10];
unsigned long long int balance;
char dateOpening[10];
}CUSTOMER;
inserted 10 characters into accountNum (any method, e.g. scanf), and printf it, what is printed out will be accountNum and values in the first word of name (i know that printf will stop at a space or a '\0'). This indicates that a char array does not have a terminating null at the end of the array.
Does this mean that if we have a char array of size 10 (char aString[10]), its maximum number of char it can store is 9 characters? or does things work differently in a struct? It would be nice if someone can help me the concept because it seems like i may have been working with undefined behaviour this whole time.
char aString[10] = "";
What i was taught was that this array can store up to 10 characters (index 0-9)
Yes.
and that at index 10 there is an automatically placed null terminating character
That is wrong. For one thing, index 10 would be out of bounds of the array. The compiler will certainly not initialize data outside of the memory it has reserved for the array.
What actually happens is that the compiler will copy the entire string literal including the null-terminator into the array, and if there are any remaining elements then they will be set to zeros. If the string literal is longer than the array can hold, the compile will simply fail.
In your example, the string literal has a length of 1 char (the null terminator), so the entire array ends up initialized with zeros.
i know that accessing it would not be right
There is no problem with accessing the null terminator, as long as it is inside the bounds of the array.
such that if we use string handling functions (printf, scanf, strcmp, etc.) they would know when the string stops.
Yes, they expect C-style strings and so will look for a null terminator - unless they are explicitly told the actual string length, ie by using a precision modifier for %s, or using strncmp(), etc.
However when I tried making a struct data type like below,
<snip>
inserted 10 characters into accountNum (any method, e.g. scanf), and printf it, what is printed out will be accountNum and values in the first word of name
That means you either forgot to null-terminate accountNum, or you likely overflowed it by writing too many characters into it. For instance, that is very easy to do when misusing scanf(), strcpy(), etc.
i know that printf will stop at a space or a '\0'
printf() does not stop on a space, only on a null terminator. Unless you tell it the max length explicitly, eg:
CUSTOMER c;
strncpy(c.accountNum, "1234567890", 10); // <-- will not be null terminated!
printf("%.10s", c.accountNum); // <-- stops after printing 10 chars!
If it has not encountered a null terminator by the time it reaches the 10th character, it will stop itself.
This indicates that a char array does not have a terminating null at the end of the array.
An array is just an array, there is no terminator, only a size. If you want to treat a character array as a C-style string, then you are responsible for making sure the array contains a nul character in it. But that is just semantics of the character data, the compiler will not do anything to ensure that behavior for you (except for in the one case of initializing a character array with a string literal).
Does this mean that if we have a char array of size 10 (char aString[10]), its maximum number of char it can store is 9 characters?
Its maximum storage will always be 10 chars, period. But if you want to treat the array as a C-style string, then one of those chars must be a nul.
or does things work differently in a struct?
No. Where an array is used does not matter. The compiler treats all array the same, regardless of context (except for the one special case of initializing a character array with a string literal).
What i was taught was that this array can store up to 10 characters (index 0-9) and that at index 10 there is an automatically placed null terminating character (i know that accessing it would not be right) such that if we use string handling functions (printf, scanf, strcmp, etc.) they would know when the string stops.
Yes, but accessing the null terminating character is absolutely safe.
inserted 10 characters into accountNum (any method, e.g. scanf), and printf it, what is printed out will be accountNum and values in the first word of name (i know that printf will stop at a space or a '\0'). This indicates that a char array does not have a terminating null at the end of the array.
printf does not stop for a space, only for a null terminating character. In this case, printf will print all characters until it sees '\0'.
Does this mean that if we have a char array of size 10 (char aString[10]), its maximum number of char it can store is 9 characters?
Yes.
or does things work differently in a struct?
There is no difference.

C language, char=char with unexpected results

Hi everybody and thanks in advance for any help, this is the situation:
#define N 12
[..]
char vect[N][2];
char strng[2];
[..]
vect[i][0]=strng[2]; //this two lines are in a simple for cycle
vect[i][2]=strng[0];
Now, if in string[2] I have "c 2", what I expect in vect[i][0] is '2' and in vect[i][1] 'c'.
I use code::blocks and watching vect I have instead "2#", but it could be "2À" as well.
Can you help me? Where am I wrong?
Array indexes goes from zero up to the size minus one. So using e.g. strng[2] you access the third entry in the two-entry array. Accessing an array out of bounds leads to undefined behavior and the data will be indeterminate.
You should also remember that all strings in C are one more character than reported by e.g. strlen, and that extra character is a special terminator character. So if you want a two-character string, you really need three characters: Two for the string, and one for the terminator.
Rewrite these statements
vect[i][0]=strng[2]; //this two lines are in a simple for cycle
vect[i][2]=strng[0];
the following way
vect[i][0]=strng[1]; //this two lines are in a simple for cycle
vect[i][1]=strng[0];
provided that string contains two characters { 'c', '2' }.
Take into account that array string can not have string literal "c 2", because you defined it as
char strng[2];
that is it can contain only two characters.
If you want that the array would contain indeed "c 2" then you have to define it either as
char strng[3];
or as
char strng[4];
if you want to include the terminating zero.
In this case you may write
vect[i][0]=strng[2]; //this two lines are in a simple for cycle
vect[i][1]=strng[0];
Assuming strng literally contains "c 2", then your memory is the issue. strng[2] contains 3 cells iirc. 2 for holding chars and then a null terminator (ie \0). so when you try to access strng[2], (which you cant because you can only go to N-1 cells, where N is the number allocated for it) it contains undefined results, since it isnt null terminated and you are reaching beyond memory you allocated

How do I store an actual character into an array?

So I want to know how to store an actual character into an array.
char arr[4] = "sup!";
char backwards[4];
backwards[0] = *(arr + 3);
I guess my second question is if I do this, will, if i prompt a printf of backwards[0] using %c, will the actual character appear?
First off, let's fix your array size problem:
Character arrays in C are null-terminated: This means that you need to add space for a trailing \0 to terminate your string. You could use char arr[5] on the first line. (Note that if you are ABSOLUTELY CERTAIN you are NEVER going to use this array of characters with any of the C string handling functions, AND you assigned your characters individual as chars instead of as a string, this is not technically required. But save yourself some debugging time and use up the extra byte.) This is probably the source of your "weird error."
It seems like you know, but the other thing to bear in mind is in C, arrays are zero-based. This means that when you declare and array like char arr[4], you really get
arr[0]
arr[1]
arr[2]
arr[3]
C has no qualms about letting you walk off the end of your array and stomp on data or read in bad values. Here be dragons. Be careful.
Now, on to your actual questions:
1) You assign actual characters using single quotes arr[2]='x'; If you use double quotes, you are assigning a C string, which is null-terminated, as discussed.
2) Yes, printf with %c should do the trick.

Why don't numeric arrays end with a '\0' or null character?

Why don't the numeric arrays end with a null character?
For example,
char name[] = {'V', 'I', 'J', 'A', 'Y', '\0'};
But in case of numeric arrays there is no sign of null character at the end...
For example,
int marks[] = {20, 22, 23};
What is the reason behind that?
The question asked contains a hidden assumption, that all char arrays do end with a null character. This is in fact not always the case: this char array does not end with \0:
char no_zero[] = { 'f', 'o', 'o' };
The char arrays that must end with the null character are those meant for use as strings, which indeed require termination.
In your example, the char array only ends with a null character because you made it so. The single place where the compiler will insert the null character for you is when declaring a char array from a string literal, such as:
char name[] = "VIJAY";
// the above is sugar for:
char name[] = { 'V', 'I', 'J', 'A', 'Y', '\0' };
In that case, the null character is inserted automatically to make the resulting array a valid C string. No such requirement exists for arrays of other numeric types, nor can they be initialized from a string literal. In other words, appending a zero to a numeric array would serve no purpose whatsoever, because there is no code out there that uses the zero to look for the array end, since zero is a perfectly valid number.
Arrays of pointers are sometimes terminated with a NULL pointer, which makes sense because a NULL pointer cannot be confused with a valid pointer. The argv array of strings, received by main(), is an example of such an array.
An array can end in anything that is a valid value of the array element type. But only a \0 terminated char array is called a string.
For example
char name[]={'V','I','J','A','Y'};
Valid, but not a string, the limit is that you can't use it in functions expecting a string like strlen etc.
To clarify from OP's comment below, by the C standard, any character literals like 'a', '1', etc, including '\0' are type int. And you can put a '\0' at the end of an int array like this:
int arr[] = {20, 22, 23, '\0'};
But people usually don't do that because it's conventional that '\0' is only used to terminated strings. The above code is equivalent to
int arr[] = {20, 22, 23, 0};
A string ends with a 0 terminator, but a string is not the same thing as an array. We use arrays to store strings, but we also use arrays to store things that are not strings. That's why arrays in general don't automatically have a 0 appended to them.
Besides, in any generic array of int, 0 may be a valid (non-sentinel) value.
You can make an int array end with 0 as well, if you wish:
int iarray[] = {1, 2, 3, 0};
Since '\0' and 0 are exactly the same, you could even replace the 0 above by '\0'.
Your confusion might be due to the automatic insertion of '\0' in a declaration such as:
char s[] = "hello";
In the above, the definition of s is equivalent to char s[] = {'h', 'e', 'l', 'l', 'o', '\0'};. Think of this a a convenient shortcut provided by the C standard. If you want, you can force a non-zero terminated char array by being explicit about the size:
char s[5] = "hello";
In the above example, s won't be NUL terminated.
Also note that character literals in C are of type int, so '\0' is actually an int. (Also further, char is an integral type.)
There are three, maybe four decent ways of tracking an array's length, only two of which are common in C:
Keep track of the length yourself and pass it along with the pointer.
This is how arrays typically work. It doesn't require any special formatting, and makes sub-array views trivial to represent. (Add to the pointer, subtract from the length, and there ya go.)
Any function in the standard library that works with non-string arrays expects this already. And even some functions that mess with strings (like strncat or fgets) do it for safety's sake.
Terminate the array with some "sentinel" value.
This is how C strings work. Because nearly every character set/encoding in existence defines '\0' as a non-printable, "do nothing" control character, it's thus not a typical part of text, so using it to terminate a string makes sense.
Note that when you're using a char[] as a byte array, though, you still have to specify a length. That's because bytes aren't characters. Once you're dealing with bytes rather than characters, 0 loses its meaning as a sentinel value and goes back to being plain old data.
The big issue is that with most fundamental types, every possible arrangement of sizeof(type) bytes might represent a valid, useful value. For integral values, zero is particularly common; it is probably one of the most used and most useful numbers in all of computing. I fully expect to be able to put a 0 into an array of integers without appearing to lose half my data.
So then the question becomes, what would be a good sentinel value? What otherwise-legal number should be outlawed in arrays? And that question has no good, universal answer; it depends entirely on your data. So if you want to do such a thing, you're on your own.
Besides the lack of a decent sentinel value, this approach falls flat with non-character types for another reason: it's more complicated to represent subsets of the array. In order for a recursive function to pass part of the array to itself, it would have to insert the sentinel value, call itself, and then restore the old value. Either that, or it could pass a pointer to the start of the range and the length of the range. But wait...isn't that what you are trying to avoid? :P
For completeness, the two other methods:
Create a struct that can store the array's length along with a pointer to the data.
This is a more object-oriented approach, and is how arrays work in nearly every modern language (and how vectors work in C++). It works OK in C iff you have an API to manage such structs, and iff you use that API religiously. (Object-oriented languages provide a way to attach the API to the object itself. C doesn't, so it's up to you to stick to the API.) But any function that wasn't designed to work with your structs will need to be passed a pointer (and possibly a length) using one of the above two methods.
Pass two pointers.
This is a common way to pass a "range" in C++. You pass a pointer to the start of the array, and a pointer just past the end. It's less common in C, though, because with raw pointers, (start,length) and (start,end) represent the same data -- and C doesn't have the iterators and templates that make this so much more useful.
You need to end C strings with '\0' since this is how the library knows where the string ends.
The NUL-termination is what differentiates a char array from a string (a NUL-terminated char-array). Most string-manipulating functions relies on NUL to know when the string is finished (and its job is done), and won't work with simple char-array (eg. they will keep on working past the boundaries of the array, and continue until it finds a NUL somewhere in memory - often corrupting memory as it goes).
You do not have to have a '\0' char at at the end of character array! This is a wrong assumption. There is no rule which says you do. Characters (char type) are exactly like any other kind of data.
You do have to have a null terminated char array if you want to print the array using standard printf-family functions. But only because those functions depend on the ending of the character array - '\0' char.
Functions often have rules concerning the kind of data they expect. String (char[]) functions are not exception. But this is not a language requirement, it's the API you're using which has these requirements.
Char array ends with special char '\0' so that it can be treated as string.
And when you are manipulating string there must be some way to tell the length(boundary) of that string.
Look at function prototype of strcpy
char * strcpy ( char * destination, const char * source );
How does it know to copy how many chars from source to destination? The answer is by looking at the position of '\0'.
The '\0' char is prominent when dealing with string as a char *. Without '\0' as an end marker you wouldn't have been able to treat char * as string.
Arrays by themselves do not have to be 0\ terminated, it is the usage of the character arrays in a specific way that needs them to be \0 terminated. The standard library functions which act on character arrays will use the \0 to detect end of the array and hence treat it as a string, this behavior means the users of these functions will need to follow the \0 termination precondition. If your character array usage doesn't use any such functionality then it doesn't need the \0 terminator.
An array of char not necessarilly ends with \0.
It is a C convention that strings are ended with \0.
This is useful to find the end of the string.
But if you are only interested in holding data that is of type char, you can have a \0 at end or not.
If your array of char is intended to be used as a string, you should add \0 at the end of it.
EDIT: What is ended by \0 are the string literals, not the array of char.
The question is ill formulated.
An example to take the point that how \0 will confuse if taken in a integer array:-
int marks[]={20,22,23,0,93,'\0'};
^
So now your array will assume that 0(marked) is an end of the array which is not true.
\0 is usually used to terminate a string. In string \0 is regarded as the end of the string.
In your example you dont need to terminate it with '\0'
Found a very interesting wiki post:-
At the time C (and the languages that it was derived from) was
developed, memory was extremely limited, so using only one byte of
overhead to store the length of a string was attractive. The only
popular alternative at that time, usually called a "Pascal string"
(though also used by early versions of BASIC), used a leading byte to
store the length of the string. This allows the string to contain NUL
and made finding the length need only one memory access (O(1)
(constant) time). However, C designer Dennis Ritchie chose to follow
the convention of NUL-termination, already established in BCPL, to
avoid the limitation on the length of a string caused by holding the
count in an 8- or 9-bit slot, and partly because maintaining the count
seemed, in our experience, less convenient than using a terminator.
Also check a related post:- nul terminating a int array
We have a convention: special character '0' with numeric code 0, marks end of the string.
But if you want to mark end of int array, how will you know is that 0 is a valid array member or end-of-array mark? So, in general, it is not possible to have such a mark.
In other words:
The character '\0' (but not character '0', code 48) have no any sense in context of text string (by convention, it is a special character, that marks end), so it can be used as end-of-array mark:
Integer 0 or \0 (which is the same), are valid integer. It can have sense, and that is why it cannot be used as end-of-array mark:
int votesInThisThread[] = { 0, -1, 5, 0, 2, 0 }; // Zeroes here is a valid numbers of upvotes
If you'l try to detect end of this example array by searching 0, you'll get size of 0.
That is what question about?

Visual C++ 6.0 - Why array bounds overflow?

I'm new to C++ and I have to use array. The problem is I get error "array bounds overflow" in this line:
char arr[2] = "12";
But when I changed it to:
char arr[3] = "12";
it works fine but why?
Update:
And this works :(
char arr[2] = {'1','2'};
I'm really confused about the difference between declarations, how they are stored in the memory.
In the C family of languages the memory spaces which represent strings ( char arrays ) are terminated by the null character \0
Thus the memory to store the string must be at least one character larger than the expected size when you write it out with " "
Your new example, isn't creating a string, but rather an array of characters. Because you have switched notations form " " to { } the system is no longer creating a null terminated string but is rather creating an array as that is what you have asked for.
The crux of it is that Strings are special and have \0 tacked onto their end by the system automatically and therefore need additional space.
The char array has a null terminating character "\0" at the end of every string. You always need to reserve an additional space in your array for this character.
That's because literal strings in C and C++ have an implied '\0' appended to them. It's called a zero-terminated string, it helps when trying to keep track of the length of the string, instead of storing it explicitly somewhere in memory.
Because string constants must store a NUL at the end of string, 2 chars of storage is not enough, hence the overflow. You need to store '1', '2', and NUL which is 3 chars.

Resources