Declare a whole string with a single charcter - c

When declaring an array in C I can write int array[100]={0} and it assigns 0 to all index. Is there any way to do the same thing with string? Because when I write char string[100]={'A'} it only assigns 'A' to the first index.And when I print the string it displays "A" instead of what I want "AAAAA.....A(99 times)". I dont want to use a loop to assign all the indexes with 'A'. So what can I do?

Its not in the standard but some compilers (including gcc and clang that I tested it with on my system) allow this:
#include <stdio.h>
int main(){
char str[100] = {[0 ... 98] = 'A'};
str[99]='\0'; // this line is really not necessary, since default is 0 and I just wrote it for clarity
printf("%s\n", str);
return 0;
}

Standard C does not have a mechanism for what you want. In particular, note that the two cases you describe are the same: that int array[100]={0} causes the array to be initialized with all zeroes is not because the specified 0 is applied to all elements, but rather that the specified 0 is applied to the zeroth element, and all otherwise uninitialized elements are initialized with a default value, which coincidentally is specified to be 0. Initialization of the char array follows the same rule.
If you want to initialize 99 elements of an array to 'A', then the initializer must provide 99 'A's. If you want to avoid typing (and counting) them all, then you might use a macro to assist:
#define REPEAT11(x) x x x x x x x x x x x
char string[100] = REPEAT11("AAAAAAAAA");
That makes use of compile-time concatenation of adjacent string literals to form the wanted initializer.

You could also use memset() from <string.h> to fill the first n bytes of your array with 'A' characters. Here is an example:
#include <stdio.h>
#include <string.h>
#define SIZE 100
int main(void) {
/* initializes all elements to 0. */
/* Will not work with 'A' as the default values of this array are 0 */
char array[SIZE] = {0};
/* fills first 99 bytes with 'A', and leaves last byte as '\0' */
memset(array, 'A', sizeof(array)-1);
printf("array = %s\n", array);
printf("length of array = %zu\n", strlen(array));
/* Outputs:
array = AAAAAAAAA...
length of array = 99
*/
return 0;
}

Related

Program never executes '0' in my string array of char

I am trying to make a simple program that can reverse a string
#include "pch.h"
#define MAX 6
int main()
{
puts("Hello and welcome. I will now reverse the word 'Hello' for you.");
char const ord[MAX] = { "Hello" };
for (size_t i = MAX; i >= 0; --i)
{
printf_s("%c", ord[i]);
}
}
However, I end up with only "ello" and some weird character like square shows up on my terminal. I tried and debug, and I think it is because the program never executes "0", so I also tried to make 'i >= 0" in my for loop, but that just leads to a critical failures and the whole program stops. Any idea what to do from here?
When you write:
#define MAX 9
int main()
{
char const ord[MAX] = "Hello";
}
You are reserving a memory area of size MAX, and writing the 6 characters 'H', 'e', 'l', 'l', 'o', '\0' to the first 6 cells of this area. Since MAX == 9 == 6+3, there are 3 remaining uninitialized cells. The 3 remaining cells are uninitialized and might contain anything; in C, trying to read the value of an uninitialized variable is undefined behaviour.
In most cases, the actual behaviour is that the 3 uninitialized cells will contain garbage, i.e., arbitrary values. So the array ord in memory looks something like:
{'H', 'e', 'l', 'l', 'o', '\0', X, Y, Z}
where X, Y and Z can be anything. If you try to print these values as characters, you might get something a bit ugly, since not all values translate to a printable ascii character.
One quick fix would be to write #define MAX 6 instead of #define MAX 9. In my opinion, this would be a bad fix. There are two different numbers here: the number of memory cells you reserve in your char array, and the actual length of the string. You should keep these two numbers clearly separate as they represent two different concepts, and your code shouldn't rely on the actual length of the string being exactly MAX. In fact, to avoid the string accidentally becoming larger than MAX, you could give yourself some latitude and write #define MAX 100 so you're certain that MAX is larger than the length of the string. Note that MAX is a constant. For the actual length of the string, you should have a variable, not a constant.
You can find out the length of a string using function strlen from header string.h, or by writing your own my_strlen.
Last issue: size_t is an unsigned type, meaning variables can never take a negative value. When a value of an unsigned type reaches 0 and you try decrementing it with i--, it "wraps around" and takes the largest possible positive value. For this reason, the loop for (size_t i = MAX; i >= 0; --i) cannot work properly: the condition will always be true and the loop will never stop. In addition, when i wraps around to a super large value, trying to access ord[i] is undefined behaviour and most likely will crash your program. Normally, your compiler should give you a warning for such an infinite loop. If it doesn't, try compiling with flags -Wall -Wextra.
#include <stddef.h> // size_t
#include <stdio.h> // printf
#define MAX 100
size_t my_strlen(char const *str);
void reverse(char *dest, char const *source, size_t len);
int main()
{
char const ord[MAX] = "Hello";
char reversed[MAX];
size_t length;
size_t i;
length = my_strlen(ord);
printf("Hello and welcome. I will now reverse the word '%s' for you.\n", ord);
reverse(reversed, ord, length);
printf("Reversed word: '%s'.\n", reversed)
return 0;
}
size_t my_strlen(char const *str)
{
size_t len;
for (len = 0; str[len] != '\0'; ++len)
{
}
return len;
}
void reverse(char *dest, char const *source, size_t len)
{
size_t i;
for (i = 0; i < len; ++i)
{
dest[i] = source[len - i];
}
dest[len] = '\0';
}
Your program first creates an array:
char const ord[MAX] = { "Hello" };
The array is represented in memory as 6 characters:
'H', 'e', 'l', 'l', 'o', '\0'
The indexes of these characters are 0, 1, 2, 3, 4, 5.
When you start your for loop, you need to start at index MAX - 1, index 5, because index 6 is not part of the array.
Another thing is that size_t is an unsigned type, meaning it can not go below 0. Because of this, i >= 0 will always be true so the loop will never end. You can use i != -1 because unsigned integer underflow is defined.

\0 when initializing a char array with a loop

I need to initialize a char array with a loop and print it. Just like that:
int main( void )
{
char array[ 10 ];
for( int i = 1; i < 10; ++i ) {
array[ i - 1 ] = i;
}
// array[] contains numbers from 1 to 9 and an unitialized subscript
printf( "%s", array );
}
I want to know if I need to put the '\0' character in array[ 9 ] or if it is already there.
In other words: once I declared char array[ 10 ]; does the last subscript contains '\0' ?
I searched for similar questions and the better I could find is this where the array is filled with a loop but till the end, leaving no space for the terminating character.
Please tell me the truth.
In other words: once I declared char array[ 10 ]; does the last subscript contains '\0' ?
No.
You define a local variable and do not initialize it. These variables are not initialized by default but hold indetermined values.
If you want to have a defined value, you need to initialize or assign it:
char array[ 10 ] = "";
This will define an array with 10 elements.
As there is an initializer, the first element will be set to 0 (=='\0') due to the provided string literal.
Furthermore all other elements will be set to 0 because you provide less initializer values than you have elements in your array.
once I declared char array[10]; does the last subscript contains '\0' ?
The answer is NO: when you define the array as an automatic variable (a local variable in a function), it is uninitialized. Hence none of its elements can be assumed to have any specific value. If you initialize the array, even partially, all elements will be initialized, either explicitly from the values provided in the initializer or implicitly to 0 if there are not enough initializers.
0 and '\0' are equivalent, they are int constants representing the value 0. It is idiomatic to use '\0' to represent the null byte at the end of a char array that makes it a C string. Note that '0' is a different thing: it is the character code for the 0 digit. In ASCII, '0' has the value 48 (or 0x30), but some ancient computers used to use different encodings where '0' had a different value. The C standard mandates that the codes for all 10 digits from 0 to 9 must be consecutive, so the digit n has the code '0' + n.
Note that the loop in your code sets the value of 9 elements of the array to non zero values, and leaves the last entry uninitialized so the array is not null terminated, hence it is not a C string.
If you want to use the char array as a C string, you must null terminate it by setting array[9] to '\0'.
Note also that you can print a char array that is not null terminated by specifying the maximum number of bytes to output as a precision field in the conversion specifier: %.9s.
Finally, be aware that array[0] = 1; does not set a valid character in the first position of array, but a control code that might not be printable. array[0] = '0' + 1; set the character '1'.
#include <stdio.h>
int main(void) {
char array[10];
/* use the element number as the loop index: less error prone */
for (int i = 0; i < 9; ++i) {
array[i] = `0` + i + 1;
}
// array[] contains numbers from 1 to 9 and an unitialized subscript
printf("%.9s\n", array); // prints up to 9 bytes from `array`
array[9] = '\0';
// array[] contains numbers from 1 to 9 and a null terminator, a valid C string
printf("%s\n", array); // produce the same output.
return 0;
}
once I declared char array[ 10 ]; does the last subscript contains '\0' ?
No. It's uninitialized. It has garbage values in every element from whatever code used the same piece of memory last.
NO, You dont need to put '\0' at the end that is array[9].
why?
because when an array (char,int,float) is uninitialized it contains garbage values.
After initializing partial or full all other elements becomes 0 or \0 in case of char array.
example:
char array[10];
all elements contains garbage value.
after intialization
char array[10]={'a' ,'b'}; all other elements automitically becomes '\0'
this is true in case of structures also.

Inner workings of c language as it pertains to character arrays

I’m wondering why this code prints a zero.
int x = 10;
char newChar[x];
printf(“%d\n”,strlen(newChar));
strlen() computes the amount of characters in a string. It counts characters up to the null character \0, which terminates a string. It returns the amount of characters read up to but not including that null character.
In your provided example the char array newChar is uninitialized; it has no string in it.
Thus, the output shall be 0.
The behavior is per standard undefined, when using uninitialized objects. In production code, Always initialize objects or, in the case of VLAs like newChar is, assign its elements with "placeholder" values or use strcpy (with VLAS of char) to copy an empty-string ("") into it, before using them in any manner.
Technically, it is possible that strlen() will return a value different than 0 on a different machine or already at a different execution of the program just because the behavior is undefined -> one or more elements could have a non-zero value followed by an element with a 0 value - making the pseudo-string effect perfect.
Maybe you wanted to calculate the number of elements in newChar.
Therefore, sizeof instead of strlen() would be appropriate:
int x = 10;
char newChar[x];
printf("%zu\n", sizeof(newChar) / sizeof(*newChar));
Online example
#include <stdio.h>
int main(void)
{
int x = 10;
char newChar[x];
printf("The number of elements in newChar is: %zu\n", sizeof(newChar) / sizeof(*newChar));
}
Output:
The number of elements in newChar is: 10

Length of a fully filled array

#include <stdio.h>
#include <string.h>
int main(void)
{
char cp [5];
cp[0]=1;
cp[1]=1;
cp[2]=1;
cp[3]=1;
cp[4]=1;
printf("%lu\n", strlen(cp));
}
If I run this program, it displays 8.(wrong)
But if I`ll change array to more than [5] (example: [6] or [7]...) with the same number of array elements, it displays 5 (right).
strlen return the number characters from the pointer you give up to a null character (not count), in your case you do not put a null character in your array, so strlen goes out of the array with an undefined behavior
for instance do
char cp [6];
cp[0]=1;
cp[1]=1;
cp[2]=1;
cp[3]=1;
cp[4]=1;
cp[5] = 0;
printf("%zu\n", strlen(cp));
also notice I changed the format, strlen returns a size_t the right format for it is %zu
out of that you put in your array characters having the code 1, that character is generally not writable, did you want '1' rather than 1 ?

memcmp with arrays of arrays

In C, I want to check a given array of chars for an arbitrary letter, and change it according to what it is. For example, the characters "a" or "A" would be changed to "4"(the character representing 4). This is a coding excercise for me :)
The code is as follows:
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <zlib.h>
#define NUM_BUFFERS 8
#define BUFFER_LENGTH 1024
char buffArrays[NUM_BUFFERS][BUFFER_LENGTH];
int main(int argc, const char* arg[v])
{
const char a[] = "a";
gzFile file;
file = gzopen("a.txt", "rb"); //contains 8 lines of 1024 'a's
int counter = 0;
while(counter < NUM_BUFFERS)
{
gzread(file, buffArrays[counter], BUFFER_LENGTH - 1);
counter++;
}
counter = 0;
while(counter < NUM_BUFFERS)
{
int i = 0;
for( i; i < BUFFER_LENGTH; i++ )
{
int *changed = &buffArrays[counter][i];
if( memcmp(&a, changed, 1) == 0 )
printf("SUCCESS\n");
}
counter++;
}
gzclose(file);
return 0;
}
This code never reaches the "SUCCESS" part. This says to me that either
(1) the value of changed is not pointing to the correct thing
(2) the pointer &a is incorrect
(3) I am completely wrong and it is something else
Any help would be appreciated.
Two things.
The following assigns the value 0x61 or 'a' to the character string.
const char a[] = 'a';
You probably rather meant to write
const char a = 'a'; /* assign a character to a character */
or
const char a[] = "a"; /* assign a string to a string */
The next thing is with the following statement. Hereby you assign a pointer to an int with the memory address of a char. Which invokes undefined behavior as you are reading over the bounds of your valid memory in the next statement.
int *changed = &bufferArrays[counter][i];
Hereby you compare the first four bytes starting from both addresses. Both variables are only one byte wide.
if( memcmp(&a, changed, 4) == 0 )
If you only want to know whether there is an 'a' in some of your buffer, why don't you just.
int i, j;
for (i = 0; i < NUM_BUFFERS; i++)
for (j = 0; j < BUFFER_LENGTH; j++)
if (bufferArrays[i][j] == 'a') printf("got it!\n");
This:
bufferArrays[counter] = "a"; //all the buffers contain one "a"
is wrong, since bufferArrays[counter] is not a character pointer but a character array. You need:
strcpy(bufferArrays[counter], "a");
Also, you don't show readTOmodify, so that part is a bit hard to understand.
Further, strings are best compared with strcpy(), which compares character-by-character and stops at the terminating '\0'. You use memcmp(), and I don't understand the reason for the 4 which is the number of bytes you're comparing.
1) bufferArrays[counter] = "a"; //all the buffers contain one "a"
This is not ok, you have to use strcpy to copy strings:
strcpy(bufferArrays[counter],"a"); //all the buffers contain one "a"
2)
#define BUFFER_LENGTH 1
Here's a problem. Buffer length should be at least 2 if you want to store just one char (for the extra null-termination).
3) In both of your loops, you never change counter, which leads to infinite loop.
Where's your code? I don't see any function surrounding it.
EDIT:
To assign you can also use:
while(counter < NUM_BUFFERS)
{
bufferArrays[counter][0] = 'a'; //all the buffers contain one "a"
counter++;
}
In any case, you have to have Buffer length as 2 if you want use it as a C-string.
The statement
bufferArrays[counter] = "a";
is not legal. It assigns a pointer to a single char and should give a compiler error (or at least a warning). Instead try
bufferArrays[counter] = 'a';
Also, in the while loops (both of them) you do not increase counter and so loop over the same index over and over forever.
Edit: Further problems
The condition where you do the comparison is flawed as well:
memcmp(&a, changed, 4)
The above doesn't compare pointers, it compares the contents of what the pointers point to, and you compare four bytes while the contents is only a single byte. Besides, you can't compare the pointers, as they will be different; The contents of the variable a is stored at a different location than that of the contents of bufferArrays[counter][i].

Resources