Let's say I have an array that looks like:
char arr[MAX_ARR_LENGTH][30] = {"Tom", "and", "Jerry" };
Now, how do I append a new string that the end of the array? Let's say I want to add "Jack" as a new element so the array shoud look like:
char arr[MAX_ARR_LENGTH][30] = {"Tom", "and", "Jerry", "Jack" };
How do you achieve this in C?
I tried using for loops but because it is a 2D array, I wasn't able to figure out the right technique.
The other answers are good and correct, but to be as simple as possible:
#define MAX_ARR_LENGTH 10
#define MAX_STR_LENGTH 30
char * arr[MAX_ARR_LENGTH][MAX_STR_LENGTH];
size_t arr_size = 0; // number of elements in use
To add an element:
if (arr_size < MAX_ARR_LENGTH)
strcpy(arr[arr_size++], "Jill");
To copy data into your existing array if there is sufficient space (MAX_ARR_LENGTH > 3):
strcpy(arr[3], "Jack");
If you are copying a variable check it's size is < 30 with strlen() first.
You cannot expand an automatic array. Instead you want to allocate it using dynamic memory:
// alternatively use calloc() or malloc()
char **arr = realloc(NULL, 30 * MAX_ARR_LENGTH);
if(!arr) {
// handle error
}
char **tmp = realloc(arr, 31 * MAX_ARR_LENGTH);
if(!tmp) {
// handle error
}
arr = tmp;
You can also use use an array syntax for allocation:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main() {
char (*arr)[30] = malloc(sizeof(char[3][30]));
strcpy(arr[0], "Tom");
strcpy(arr[1], "and");
strcpy(arr[2], "Jerry");
char (*tmp)[30] = realloc(arr, sizeof(char[4][30]));
if(!tmp) {
// handle error
}
arr = tmp;
strcpy(arr[3], "Jack");
}
In this declaration
char arr[MAX_ARR_LENGTH][30] = {"Tom", "and", "Jerry" };
you declared an array of MAX_ARR_LENGTH elements of the type char[30] and initialized it with three string literals.
I suppose that the value of MAX_ARR_LENGTH is greater than 3.
In this case all other elements of the array that were not explicitly initialized by the string literals are implicitly initialized by zero. It means that all other elements are initialized as empty strings.
So to append a new string to the array you can write for example
#include <string.h>
//...
size_t i = 0;
while ( i < MAX_ARR_LENGTH && arr[i][0] != '\0' ) ++i;
if ( i < MAX_ARR_LENGTH ) strcpy( arr[i], "Jack" );
Here is a demonstration program.
#include <stdio.h>
#include <string.h>
#define MAX_ARR_LENGTH 10
int main( void )
{
char arr[MAX_ARR_LENGTH][30] = { "Tom", "and", "Jerry" };
for (size_t i = 0; i < MAX_ARR_LENGTH && arr[i][0] != '\0'; i++)
{
printf( "%s ", arr[i] );
}
putchar( '\n' );
size_t i = 0;
while (i < MAX_ARR_LENGTH && arr[i][0] != '\0') ++i;
if (i < MAX_ARR_LENGTH) strcpy( arr[i], "Jack" );
for (size_t i = 0; i < MAX_ARR_LENGTH && arr[i][0] != '\0'; i++)
{
printf( "%s ", arr[i] );
}
putchar( '\n' );
}
The program output is
Tom and Jerry
Tom and Jerry Jack
On the other hand, it will be better to track the number of actually initialized elements from the very beginning.
Here is another demonstration program.
#include <stdio.h>
#include <string.h>
#define MAX_ARR_LENGTH 10
int main( void )
{
char arr[MAX_ARR_LENGTH][30] = { "Tom", "and", "Jerry" };
size_t n = 0;
while (n < MAX_ARR_LENGTH && arr[n][0] != '\0') ++n;
for (size_t i = 0; i < n; i++)
{
printf( "%s ", arr[i] );
}
putchar( '\n' );
if (n < MAX_ARR_LENGTH) strcpy( arr[n], "Jack" );
++n;
for (size_t i = 0; i < n; i++)
{
printf( "%s ", arr[i] );
}
putchar( '\n' );
}
The program output is the same as shown above
Tom and Jerry
Tom and Jerry Jack
Related
I'm recently practicing looping. I learned how to print: for example home to h ho hom home. by using
#include <stdio.h>
#include <string.h>
int main (){
char s[100];
printf("Input string = ");
scanf("%[^\n]", s);
for (int i=1; i<=strlen(s); i++){
for(int j = 0; j<i; j++)
printf("%c", s[j]);
printf("\n");
}
return 0;
How can i reverse it so it can be
home
hom
ho
h
instead? thank you.
It is easy to do. For example
for ( size_t i = strlen( s ); i != 0; i-- )
{
for ( size_t j = 0; j < i; j++ )
{
putchar( s[j] );
}
putchar( '\n' );
}
Another way is the following
for ( size_t i = strlen( s ); i != 0; i-- )
{
printf( ".*s\n", ( int )i, s );
}
provided that an object of the type int is able to store the length of the passed string.
Here is a demonstration program.
#include <stdio.h>
#include <string.h>
int main( void )
{
const char *s = "home";
for (size_t i = strlen( s ); i != 0; i--)
{
printf( "%.*s\n", ( int )i, s );
}
}
The program output is
home
hom
ho
h
You could loop over the string using putc, but it might also be helpful to understand the destructive approach that shortens the string and uses %s to print strings. eg:
#include <stdio.h>
#include <string.h>
int
main(int argc, char **argv)
{
char *s = argc > 1 ? argv[1] : strdup("home");
for( char *e = s + strlen(s); e > s; e -= 1 ){
*e = '\0';
printf("%s\n", s);
}
return 0;
}
Note that this approach is destructive. When complete, the string is null. As an exercise, it might be helpful to fix that.
You'll basically go backwards in your loop.
Instead of:
for (int i=1; i<=strlen(s); i++){
You'd have
for (int i=strlen(s); i>0; i--){
I am trying to merge multiple string array tokens into one, for example:
char* args = { "zero" , "one', "two"}
Noting that args is not a set size, it could be 1 or 100
I want to make a new array
char* array ={"one two"}
with the spaces in between.
I tried this:
char* array;
int i=1;
for(i=1; i< sizeof(args)-1 ; i++){
strcat(array, args[i]);
}
but kept getting a segmentation fault.
This is the code I am using, need to add function that combines all of my args from 1 (not zero since arg[0] has a command) to whatever size:
else if ( (args[1] != NULL) && (strchr(args[1], '=') != NULL) ) {
memcpy(aliasCommands[aliasCount], args[1], 512 );
printf("Save Alias\n");
printf("Alias Added : %s\n", aliasCommands[aliasCount]);
aliasCount++;
printf("Alias Number : %d\n", aliasCount);
}
Instead of only args[1], I want to pass args[1] space args[2] and so on
Lets say that
args[1]={"command='ls"}
args[2]={"cd'"}
and so on, args could be up to 512. I want to pass them all as one string in
aliasCommand[aliasCount] = {"command='ls cd'"}
You have several problems
You don't calculate the number of elements properly
You don't have room to store the result
strcat wants a nul terminated string
I will use snprintf instead of strcat in order to avoid buffer overflows, something like:
#include <stdio.h>
int main(void)
{
char *args[] = {"zero", "one", "two"};
char str[32];
size_t len = 0;
for (size_t i = 0; i < sizeof args / sizeof *args; i++)
{
len += (size_t)snprintf(str + len, (sizeof str) - len, "%s ", args[i]);
}
// Remove the last space
str[len - 1] = '\0';
printf("<%s>\n", str);
return 0;
}
Output:
<zero one two>
For starters the initializers used in this declaration (where you forgot to place a semicolon)
char* args[] = { 'zero' , 'one', 'two'};
are not string literals but multibyte integer character constants that have implementation defined values.
It seems you mean
char * args[] = { "zero" , "one", "two" };
Also this declaration of an array (where you again are using an integer character constant instead of a string literal)
char* array[]={'zero one two'}
does not make a great sense because it is equivalent to
char* array[1]={'zero one two'}
It seems you mean
char *array={ "zero one two" }
What you need is to allocate dynamically an enough large array and copy the string literal pointed to in the array args in the array array.
Here is a demonstrative program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main( void )
{
char * args[] = { "zero" , "one", "two" };
const size_t N = sizeof( args ) / sizeof( *args );
size_t n = 0;
for (size_t i = 0; i < N; i++) n += strlen( args[i] );
char *array = malloc( n + N );
if (array != NULL)
{
size_t n = 0;
array[0] = '\0';
for (size_t i = 0; i < N; i++)
{
if (i != 0)
{
array[n] = ' ';
array[++n] = '\0';
}
strcpy( array + n, args[i] );
n += strlen( args[i] );
}
puts( array );
}
free( array );
}
The program output is
zero one two
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#pragma warning(disable:4996)
#define SIZE 100
int main(void){
char str[SIZE];
char str2[SIZE];
int i;
int len;
gets(str);
len = strlen(str);
for (i = 0; str[i] != NULL; i++) {
if (str[i] != ' '){
str2[i] = str[i];
}
}
for (i = 0; i < len; i++){
printf("%c", str2[i]);
}
return 0;
}
It returns the following error:
What is the problem?
I just want to copy some elements in str to str2 without spaces, but when I run, it has got some weird letters.
You need two index variables
one to go through str
one to tell where to write next to str2
code:
len = strlen(str);
int j;
for (i=0, j=0 ; str[i] != '\0' ; i++) {
if (str[i] != ' '){
str2[j++] = str[i]; // store to str2 and increment j
}
}
Then store a final \0 to str2 at index j
str2[j] = '\0';
Finally, to print the result, you can do that one shot
printf("%s\n", str2);
instead of printing one char at a time.
For starters these headers
#include <stdlib.h>
#include <windows.h>
can be removed because neither declaration from the headers is used in the program.
The function gets is unsafe and is not supported by the C Standard any more. Instead use standard C function fgets.
When str is copied in str2 you have to use separate index to access characters in str2 because some characters from str are not copied. Otherwise the array str2 will contain gaps. As result you can not use the previous value of the variable len with the array str2.
Also it is desirable not to copy any other white space characters.
The program can look the following way
#include <stdio.h>
#include <ctype.h>
#define SIZE 100
int main(void)
{
char str[SIZE];
char str2[SIZE];
fgets( str, sizeof( str ), stdin );
const char *p = str;
char *p2 = str2;
do
{
if ( !isspace( ( unsigned char )*p ) )
{
*p2++ = *p;
}
} while ( *p++ );
for ( p2 = str2; *p2; ++p2 )
{
printf( "%c", *p2 );
}
return 0;
}
Its output might be
Hello World
HelloWorld
If you do not study yet pointers then the program can look like
#include <stdio.h>
#include <ctype.h>
#define SIZE 100
int main(void)
{
char str[SIZE];
char str2[SIZE];
fgets( str, sizeof( str ), stdin );
size_t i = 0, j = 0;
do
{
if ( !isspace( ( unsigned char )str[i] ) )
{
str2[j++] = str[i];
}
} while ( str[i++] );
for ( j = 0; str2[j]; ++j )
{
printf( "%c", str2[j] );
}
return 0;
}
Given an array of character strings such as...
char *example[] = {"s", "ss", "sss"};
How can I write a function to count the total number of chars in the array including the terminating characters, without using the standard library for strlen() etc.
Follows is my attempt
int countChars(char *array[], int len)
{
int total = 0, count = 0;
for (int i = 0; i < len; i++)
{
if (array[i] != NULL)
{
while (*array[i] != '\0') {
count++;
}
count++;
}
total += count;
}
return total;
}
An explanation on how char *array[] actually works for access wold be appreciated. I believe that it is supposed to be an array of pointers to strings.
You have to increment the index to consider each of the character.
Something like this:-
for (int i = 0; i < len; i++)
{
if (array[i] != NULL)
{
int j=0,count=0;
while (array[i][j++] != '\0') {
count++;
}
total += count;
}
}
Also reset the count or add to total at the end of all the calculation.
As an answer to your second question:-
char* array[] is basically denoting an array pointers each pointing
to the string literals with which you initialized it.
So once you use array[i] you should now think that it is nothing
other than a pointer to a string literal.
You need to reinitialize the variable count inside the for loop for each processed string and to increase the expression *array[i] inside the while loop.
Also it is better when the function has the return type size_t (size_t is the type that is returned by the standard C function strlen and by the operator sizeof)
The function can look as it is shown in the demonstrative program.
#include <stdio.h>
size_t countChars( const char *array[], size_t n )
{
size_t count = 0;
while ( n-- )
{
if ( array[n] )
{
size_t i = 0;
do { ++count; } while ( array[n][i++] );
}
}
return count;
}
int main(void)
{
const char * example[] = { "s", "ss", "sss" };
printf( "%zu\n", countChars( example, sizeof( example ) / sizeof( *example ) ) );
return 0;
}
The program output is
9
Each element of this array
char *example[] = {"s", "ss", "sss"};
has type char * and is a pointer to the first character of the corresponding string literal.
Since your array contains string constants you should declare it with const:
const char *example[3];
Without const the compiler will not warn you if you try to assign a character to example[i][j]. For the same reason the formal parameter should also be declared with const.
For a pure function with no side effects it is better to name it so that it reflects the result. Therefor I would use charCount instead of countChars (or maybe totalLength). The focus should be on a noun (namely count or length).
Here is my solution:
#include <stdio.h>
#define LEN(a) (sizeof (a) / sizeof (a)[0])
static int CharCount(const char *strings[], int len)
{
int result, i, j;
result = 0;
for (i = 0; i < len; i++) {
j = 0;
while (strings[i][j] != '\0') {
result++;
j++;
}
}
return result;
}
int main(void)
{
const char *strings[] = { "s", "ss", "sss" };
printf("character count: %d\n", CharCount(strings, LEN(strings)));
}
The length macro LEN is very convenient and is the least error prone way to handle array lengths.
Yes char *array[] = {"aa", "bb", "cc"} is an array of pointers to strings.
array[0] points to "aa"
array[1] points to "bb"
array[2] points to "cc"
You probably want this:
int countChars(char *array[], int len)
{
int count = 0;
for (int arrayindex = 0; arrayindex < len; arrayindex++)
{
const char *stringptr = array[arrayindex];
// stringptr will point successively
// to "s", to "ss" and to "sss"
while (*stringptr++)
count++; // increment count until NUL character encountered
count++; // one more for NUL character
}
return count;
}
int main() {
char *example[] = { "s", "ss", "sss" };
int x = countChars(example, 3); // x contains 9 after the call to countChars
// that is 2 + 3 + 4
}
Instead of hard coding 3 you could use sizeof(example) / sizeof(example[0]).
I have an array of char pointers (string array), which contains some duplicate values. I've found an algorithm that truncates the array by removing its duplicate values.
Here is a code sample :
int i, j , k;
int n = 10;
char *teams[n];
for(i=0;i<n;i++){
for(j=i+1;j<n;){
if(*(team[j]==*(team[i])){
for(k=j;k<n;k++){
//strcpy(team[k], team[k+1]);
team[k] = team[k+1];
}
n--;
}else{
j++;
}
}
}
I've read that the only way to copy strings between string arrays is to use strcpy(s1, s2). But in my case I can't use it, because strcpy function permits to copy s2 into s1 only if s2 has a lenght equal or bigger than the lenght of s1. So how can I implement this algorithm if I can't put the string pointed by the pointer team[k+1] in team[k] ?
It seems you need to remove duplicated string representations instead of duplicated addresses to strings.
If so then this if statement (if to add missed closed parenthesis)
if( *(team[j] ) ==*( team[i] ) ){
compares only first characters of strings instead of comparing strings pointed to by the pointers.
In this loop
for(k=j;k<n;k++){
//strcpy(team[k], team[k+1]);
team[k] = team[k+1];
}
each time when a duplicates string is found there is copied the whole array of pointers. Moreover there is an attempt to access memory beyond the array in this statement when k is equal to n-1
team[k] = team[k+1];
^^^^
You can write a separate function that will "remove" duplicates. The function can for example return pointer after the last unique element in the modified array.
#include <stdio.h>
#include <string.h>
char ** unique( char *s[], size_t n )
{
size_t i = 0;
for ( size_t j = 0; j < n; j++ )
{
size_t k = 0;
while ( k < i && strcmp( s[k], s[j] ) != 0 ) ++k;
if ( k == i )
{
if ( i != j ) s[i] = s[j];
++i;
}
}
return s + i;
}
int main(void)
{
char * s[] = { "A", "B", "A", "C", "A" };
const size_t N = sizeof( s ) / sizeof( *s );
for ( size_t i = 0; i < N; i++ ) printf( "%s ", s[i] );
printf( "\n" );
char **p = unique( s, N );
size_t n = p - s;
for ( size_t i = 0; i < n; i++ ) printf( "%s ", s[i] );
printf( "\n" );
return 0;
}
The program output is
A B A C A
A B C
#include <stdio.h>
#include <string.h>
unsigned dedup(char **arr, unsigned count)
{
unsigned this, that ;
for(this=0;this<count;this++){
for(that=this+1;that<count;){
if( strcmp(arr[that], arr[this])) {that++; continue; }
#if PRESERVE_ORDER
memmove(arr+that, arr+that+1, (--count - that) * sizeof arr[that] );
#else
arr[that] = arr[--count];
#endif
}
}
return count; /* the count after deduplication */
}
char *array[] = { "one", "two", "three", "two", "one", "four", "five", "two" };
int main(void)
{
unsigned count, index;
count = dedup(array, 8);
for (index = 0; index < count; index++) {
printf("%s\n", array[index] );
}
return 0;
}
[UPDATED]: I added the PRESERVE_ORDER version