Getting first string from string array in c - c

I am trying to create processes for my project. I will pas arguments to child process from parent and the argument will change in time, so i wanted to make a try first with passing 1 to the child. The string format should be like this "childname.exe c" where c represents random character (in this case it is 1 for just trial).
I created a childname array and and all i wanted was concatenate the new string with childname string and copy it to another string array(lpCommandLine variable). When i debugged the code below i saw that child_name[0] (when i is equal to 0) returns only 'C' although i expected it to return "ChildProj1.exe". Is there a point that i missed or how to do it in c?
here there is a image of what i getin debugger: here stored values of in variables
#define NO_OF_PROCESS 3
char *child_names[]= {"ChildProj1.exe", "ChildProj2.exe", "ChildProj3.exe" };
char* lpCommandLine[NO_OF_PROCESS];
int i;
for (i = 0; i < NO_OF_PROCESS; i++)
lpCommandLine[i] = (char *)malloc(sizeof(char) * 16);
for (i = 0; i < NO_OF_PROCESS; i++)
{
strcat_s(child_names[i], strlen(child_names[i]), " 1");
strcpy_s(lpCommandLine[i], strlen(lpCommandLine[i]), child_names[i]);
}

From your description it follows that you want to get strings like this
"childname.exe c"
However this loop
for (i = 0; i < NO_OF_PROCESS; i++)
{
strcat_s(child_names[i], strlen(child_names[i]), " 1");
strcpy_s(lpCommandLine[i], strlen(lpCommandLine[i]), child_names[i]);
}
does not do what you want.
This loop has undefined behavior because in this statement
strcat_s(child_names[i], strlen(child_names[i]), " 1");
there is an attempt to modify a string literal. You may not change string literals neither in C nor in C++.
Moreover in this statement
strcpy_s(lpCommandLine[i], strlen(lpCommandLine[i]), child_names[i]);
this call
strlen(lpCommandLine[i])
also has undefined behavior because array pointed to by this pointer lpCommandLine[i] does not has the terminating zero.
There is no any need to use the functions strcat_s and strcpy_s. It is much better to use standard function strcat and strcpy.
What you is the following that is shown in this demonstrative program.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NO_OF_PROCESS 3
int main(void)
{
const char * child_names[]=
{
"ChildProj1.exe",
"ChildProj2.exe",
"ChildProj3.exe"
};
const char *s = " 1";
size_t n = strlen( s );
char* lpCommandLine[NO_OF_PROCESS];
for ( int i = 0; i < NO_OF_PROCESS; i++ )
{
lpCommandLine[i] = ( char * )malloc( strlen( child_names[i] ) + n + 1 );
}
for ( int i = 0; i < NO_OF_PROCESS; i++ )
{
strcpy( lpCommandLine[i], child_names[i] );
strcat( lpCommandLine[i], s );
}
for ( int i = 0; i < NO_OF_PROCESS; i++ ) puts( lpCommandLine[i] );
for ( int i = 0; i < NO_OF_PROCESS; i++ ) free( lpCommandLine[i] );
return 0;
}
The program output is
ChildProj1.exe 1
ChildProj2.exe 1
ChildProj3.exe 1

Instead of char * child_names[] did you mean something like char[][] child_names, char[] * child_names, or char ** child_names?

to do the string concat do
size_t sz = strlen(child_names[i]) + 3; // space, '1' and \0
char *buff = malloc(sz);
strcat_s(buff,sz,child_names[i]);
strcat_s(buff,sz," 1");

Related

Checking whether a string consists of two repetitions

I am writing a function that returns 1 if a string consists of two repetitions, 0 otherwise.
Example: If the string is "hellohello", the function will return 1 because the string consists of the same two words "hello" and "hello".
The first test I did was to use a nested for loop but after a bit of reasoning I thought that the idea is wrong and is not the right way to solve, here is the last function I wrote.
It is not correct, even if the string consists of two repetitions, it returns 0.
Also, I know this problem could be handled differently with a while loop following another algorithm, but I was wondering if it could be done with the for as well.
My idea would be to divide the string in half and check it character by character.
This is the last function I tried:
int doubleString(char *s){
int true=1;
char strNew[50];
for(int i=0;i<strlen(s)/2;i++){
strNew[i]=s[i];
}
for(int j=strlen(s)/2;j<strlen(s);j++){
if(!(strNew[j]==s[j])){
true=0;
}
}
return true;
}
The problem in your function is with the comparison in the second loop: you are using the j variable as an index for both the second half of the given string and for the index in the copied first half of that string. However, for that copied string, you need the indexes to start from zero – so you need to subtract the s_length/2 value from j when accessing its individual characters.
Also, it is better to use the size_t type when looping through strings and comparing to the results of functions like strlen (which return that type). You can also improve your code by saving the strlen(s)/2 value, so it isn't computed on each loop. You can also dispense with your local true variable, returning 0 as soon as you find a mismatch, or 1 if the second loop completes without finding such a mismatch:
int doubleString(char* s)
{
char strNew[50] = { 0, };
size_t full_len = strlen(s);
size_t half_len = full_len / 2;
for (size_t i = 0; i < half_len; i++) {
strNew[i] = s[i];
}
for (size_t j = half_len; j < full_len; j++) {
if (strNew[j - half_len] != s[j]) { // x != y is clearer than !(x == y)
return 0;
}
}
return 1;
}
In fact, once you have appreciated why you need to subtract that "half length" from the j index of strNew, you can remove the need for that temporary copy completely and just use the modified j as an index into the original string:
int doubleString(char* s)
{
size_t full_len = strlen(s);
size_t half_len = full_len / 2;
for (size_t j = half_len; j < full_len; j++) {
if (s[j - half_len] != s[j]) { // x != y is clearer than !(x == y)
return 0;
}
}
return 1;
}
This loop
for(int j=strlen(s)/2;j<strlen(s);j++){
if(!(strNew[j]==s[j])){
true=0;
}
}
is incorrect. The index in the array strNew shall start from 0 instead of the value of the expression strlen( s ) / 2.
But in any case your approach is incorrect because at least you are using an intermediate array with the magic number 50. The user can pass to the function a string of any length.
char strNew[50];
The function can look much simpler.
For example
int doubleString( const char *s )
{
int double_string = 0;
size_t n = 0;
if ( ( double_string = *s != '\0' && ( n = strlen( s ) ) % 2 == 0 ) )
{
double_string = memcmp( s, s + n / 2, n / 2 ) == 0;
}
return double_string;
}
That is the function at first checks that the passed string is not empty and its length is an even number. If so then the function compares two halves of the string.
Here is a demonstration program.
#include <stdio.h>
#include <string.h>
int doubleString( const char *s )
{
int double_string = 0;
size_t n = 0;
if (( double_string = *s != '\0' && ( n = strlen( s ) ) % 2 == 0 ))
{
double_string = memcmp( s, s + n / 2, n / 2 ) == 0;
}
return double_string;
}
int main( void )
{
printf( "doubleString( \"\" ) = %d\n", doubleString( "" ) );
printf( "doubleString( \"HelloHello\" ) = %d\n", doubleString( "HelloHello" ) );
printf( "doubleString( \"Hello Hello\" ) = %d\n", doubleString( "Hello Hello" ) );
}
The program output is
doubleString( "" ) = 0
doubleString( "HelloHello" ) = 1
doubleString( "Hello Hello" ) = 0
Pay attention to that the function parameter should have the qualifier const because the passed string is not changed within the function. And you will be able to call the function with constant arrays without the need to defined one more function for constant character arrays.
it's better to do it with a while loop since you don't always have to iterate through all the elements of the string but since you want the for loop version here it is (C++ version):
int doubleString(string s){
int s_length = s.length();
if(s_length%2 != 0) {
return 0;
}
for (int i = 0; i < s_length/2; i++) {
if (s[i] != s[s_length/2 + i]){
return 0;
}
}
return 1;
}

C: Problem in comparing two strings in a function

Good morning everyone, I have to simulate the operation of the strstr() function with a function written by me.
In the code I slide the original string in a temporary string and then the comparison with the string to look for, if they are equal it should return 1.
But even if the strings are equal and of the same length the code never enters the if cycle and therefore never returns 1.
My code:
int *strstr_new(char *s7, char *s8) {
int length_s7 = strlen(s7);
int length_s8 = strlen(s8);
char search_string[length_s8];
printf("%d\n", length_s8);
for(int i=0; i<length_s7; i++) {
for(int j=0; j<length_s8; j++) {
search_string[j] = s7[i+j];
search_string[j+1] = '\0';
}
printf("%s\n", s8);
printf("%s\n", search_string);
printf("%d\n", length_s8);
printf("%d\n", strlen(search_string));
//search_string[length_s8+1] = '\0';
if(search_string == s8) {
return(1);
}
}
if(search_string != s8) {
return(NULL);
}}
Does someone have an idea of where I'm wrong?
Thanks!
The function declaration
int *strstr_new(char *s7, char *s8);
looks very strange.
For example why is the return type int *?
Why are function parameters named s7 and s8 instead of for example s1 and s2?
Why are not the function parameters qualified with const?
Creating a variable length array within the function is inefficient and redundant and can lead to stack exhaustion.
char search_string[length_s8];
This loops
for(int j=0; j<length_s8; j++) {
search_string[j] = s7[i+j];
search_string[j+1] = '\0';
}
invokes undefined behavior because this statement
search_string[j+1] = '\0';
writes beyond the array when j is equal to length_s8 - 1.
In this statement
if(search_string == s8) {
there are compared two pointers and it is evident that they are unequal because they point to different arrays.
Without using standard C functions except the function strlen (that could be also defined explicitly) the function can be declared and defined the following way
#include <stdio.h>
#include <string.h>
char * strstr_new( const char *s1, const char *s2 )
{
char *p = NULL;
size_t n1 = strlen( s1 );
size_t n2 = strlen( s2 );
if ( !( n1 < n2 ) )
{
for ( size_t i = 0, n = n1 - n2 + 1; p == NULL && i < n; i++ )
{
size_t j = 0;
while ( j < n2 && s1[i + j] == s2[j] ) ++j;
if ( j == n2 ) p = ( char * )( s1 + i );
}
}
return p;
}
int main( void )
{
const char *s1 = "strstr_new";
const char *s2 = "str";
for ( const char *p = s1; ( p = strstr_new( p, s2 ) ) != NULL; ++p )
{
puts( p );
}
}
The program output is
strstr_new
str_new
If you are allowed to use standard string functions along with strlen then the loop within the function strstr_new can be simplified the following way
for ( size_t i = 0, n = n1 - n2 + 1; p == NULL && i < n; i++ )
{
if ( memcmp( s1 + i, s2, n2 ) == 0 ) p = ( char * )( s1 + i );
}
The biggest problem in your code is comparing strings with == operator. Both search_string and s8 are char pointers, which means you're comparing addresses of different variables, obviously to return False. Try adding another for loop to compare each char in search_string to the corresponding char in s8 (using the dereferencing operator *).
Your string comparisons won't work because you are comparing the addresses of those strings instead of the strings themselves, you'd what to use something like strcmp or memcmp to compare two strings.
Your return type is also not compatible with the return you have particularly if the strings match. I'd return 1 if the string is found and 0 if it's not, for that you'd need to change the return type to int only.
The second string comparison is unneeded, you already test the existance of the substring inside the loop so you just need to return 0 if the loop finds it's way to the end.
Lastly the temporary string is too short and will allow for access outside its bounds, inside the loop.
e.g. if length_s8 is 4 will write to
search_string[4], 5th index, out the bounds of the array.
int strstr_new(char *s7, char *s8) //return 1 for found, 0 for not found
{
int length_s7 = strlen(s7);
int length_s8 = strlen(s8);
char search_string[length_s8 + 1];//you'd want to avoid buffer overflow
for (int i = 0; i < length_s7; i++)
{
for (int j = 0; j < length_s8; j++)
{
search_string[j] = s7[i + j];
search_string[j + 1] = '\0';
}
if (!strcmp(search_string, s8))
{
return 1; //if the string is found return 1 immediately
}
}
return 0; //if it reaches this point, no match was found
}
A couple of tests:
printf("%d\n", strstr_new("this is my string", "this i"));
printf("%d\n", strstr_new("this is my string", "ringo"));
printf("%d\n", strstr_new("this is my string", "ring"));
printf("%d\n", strstr_new("this is my strin", "ths"));
Output:
1
0
1
0

Is there any proper way how to put integer into string? [C]

I have code like this:
char str[100];
int r = 0;
for(int k = 0; k < i;k++){
str[r++] = y[k];
sprintf(str[r], str, x[k]);
r++;
}
I want in array y I have only alphabetic characters(e.g C,D...) and in array x I have only numbers. I want to make string like "C50D80E20" etc."
But I dont know how to put interger into string(I know I´m using sprintf wrong and also that it shouldn´t be used in this case).
Thanks in advance.
Here you are.
#include <stdio.h>
int main(void)
{
enum { N = 100 };
char s[N];
char a[] = "CDE";
int b[] = { 50, 80, 20 };
int pos = 0;
for ( size_t i = 0; i + 1 < sizeof( a ); i++ )
{
pos += sprintf( s + pos, "%c%d", a[i], b[i] );
}
s[pos] = '\0';
puts( s );
return 0;
}
The program output is
C50D80E20
This statement
s[pos] = '\0';
is required only in the case when there are no values to append to the array s that is when none call of sprintf was executed.
If you want to get a string like this
C50 D80 E20
then just write for example
pos += sprintf( s + pos, "%c%d%c", a[i], b[i], ' ' );
And if you want to remove the last space character then instead of
s[pos] = '\0';
write
s[ pos == 0 ? pos : pos - 1 ] = '\0';
Instead of the function sprintf you could use the function snprintf. But it does not resolve the problem if you allocated not enough memory for the result string because in any case you will not get the expected result in such a case.
As for the function itoa then it is not a standard C function.
Use itoa().
Somthing like that:
itoa(y[k], str[r++], 10);
Here's a link about itoa().
UPDT:
Or as correctly commentator marked - you can use int + '0'
Is there any proper way how to put integer into string? [C]
Use snprintf().
Check results.
char str[N];
int len = snprintf(str[r], sizeof str, "%d", x[k]);
if (len < 0 || (unsigned)len >= sizeof str) Handle_Error();

Error: assignment to expression with array type while using selection-sort

Basically, I'm trying to sort an agenda with 3 names using selection sort method. Pretty sure the selection sort part is OK. The problem is that apparently my code can identify the [0] chars of the string, but cannot pass one string to another variable. Here is my code:
include <stdio.h>
typedef struct{
char name[25];
} NAME;
int main(){
int a, b;
char x, y[25];
static NAME names[]={
{"Zumbazukiba"},
{"Ademiro"},
{"Haroldo Costa"}
};
for(a=0; a<4; a++){
x = names[a].name[0];
y = names[a];
for(b=(a-1); b>=0 && x<(names[b].name[0]); b--){
names[b+1] = names[b];
}
names[b+1].name = y;
}
}
I keep getting this error message:
main.c:21:11: error: assignment to expression with array type
y = names[a];
There are at least two errors in your code, in the line flagged by your compiler. First, you can't copy character strings (or, indeed, any other array type) using the simple assignment (=) operator in C - you need to use the strcpy function (which requires a #include <string.h> line in your code).
Second, you have declared y as a character array (char y[25]) but names is an array of NAME structures; presumably, you want to copy the name field of the given structure into y.
So, instead of:
y = names[a];
you should use:
strcpy(y, names[a].name);
Feel free to ask for further clarification and/or explanation.
For starters I do not see the selection sort. It seems you mean the insertion sort.
Arrays do not have the assignment operator. So statements like this
names[b+1].name = y;
where you are trying to assign an array are invalid.
And in statements like this
y = names[a];
you are trying to assign an object of the structure type to a character array.
Moreover the loops are also incorrect.
The array has only 3 elements. So it it is unclear what the magic number 4 is doing in this loop
for(a=0; a<4; a++){
and this loop
for(b=(a-1); b>=0 && x<(names[b].name[0]); b--){
skips the first iteration when a is equal to 0.
Here is a demonstrative program that shows how the selection sort can be applyed to elements of your array.
#include <stdio.h>
#include <string.h>
#define LENGTH 25
typedef struct
{
char name[LENGTH];
} NAME;
int main(void)
{
NAME names[] =
{
{ "Zumbazukiba" },
{ "Ademiro" },
{ "Haroldo Costa" }
};
const size_t N = sizeof( names ) / sizeof( *names );
for ( size_t i = 0; i < N; i++ )
{
puts( names[i].name );
}
putchar( '\n' );
for ( size_t i = 0; i < N; i++ )
{
size_t min = i;
for ( size_t j = i + 1; j < N; j++ )
{
if ( strcmp( names[j].name, names[min].name ) < 0 )
{
min = j;
}
}
if ( i != min )
{
NAME tmp = names[i];
names[i] = names[min];
names[min] = tmp;
}
}
for ( size_t i = 0; i < N; i++ )
{
puts( names[i].name );
}
putchar( '\n' );
return 0;
}
The program output is
Zumbazukiba
Ademiro
Haroldo Costa
Ademiro
Haroldo Costa
Zumbazukiba

How to get rid of garbage characters in this program?

This program is supposed to print an input string backwards. Every single time it happens, though, I get garbage characters such as \340 or of the like. Why is it doing that? Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char mattsentence[51];
mattsentence[50] = '\0';
gets(mattsentence);
char mask[sizeof(mattsentence)];
int i, j;
j = sizeof(mattsentence);
for (i = 0; i < sizeof(mask); i++)
{
j = j - 1;
mask[i] = mattsentence[j];
printf("%c", mask[i]);
}
printf("\n");
}
Your approach is wrong because you reverse the entire character array while it can be filled only partially. You should use standard C function strlen declared in header <string.h> that to determine the size of the entered string. Also to use gets is unsafe because you can overwrite memory beyond the character array. It now is excluded from the C Standard
Here is shown how the program can be written.
#include <stdio.h>
#include <string.h>
#define N 51
int main(void)
{
char mattsentence[N] = { '\0' };
char mask[N] = { '\0' };
fgets( mattsentence, sizeof( mattsentence ), stdin );
size_t n = strlen( mattsentence );
if ( n != 0 && mattsentence[n-1] == '\n' ) mattsentence[--n] = '\0';
for ( size_t i = 0; n != 0; i++ )
{
mask[i] = mattsentence[--n];
printf( "%c", mask[i] );
}
printf( "\n" );
return 0;
}
If to enter
Hello, Christiana S. F. Chamon
then the program output will be
nomahC .F .S anaitsirhC ,olleH
Take into account that to output a string in the reverse order there is no need to define a second character array.
If you want only to output the source string in the reverse order then the program can look like
#include <stdio.h>
#include <string.h>
#define N 51
int main(void)
{
char mattsentence[N] = { '\0' };
fgets( mattsentence, sizeof( mattsentence ), stdin );
size_t n = strlen( mattsentence );
if ( n != 0 && mattsentence[n-1] == '\n' ) mattsentence[n-1] = '\0';
while ( n != 0 )
{
printf( "%c", mattsentence[--n] );
}
printf( "\n" );
return 0;
}
sizeof() operator gives the size of the datatype. So, sizeof(mattsentence) will give you a value of 51. Then, sizeof(mask) will give you 51 again.
When you use that sizeof(mask) as for loop condition, you're basically going past the actual input values, thus pritning out garbage values.
What you want here is to use strlen() to find out the actual valid length of the entered string.
So, basically you need to take care of
Point 1: replace sizeof with strlen().
Point 2: Use of gets() is dangerous. Please use fgets() instead of gets().
Point 3: int main() should be int main(void). Put an expilicit return statement at the end of main(). Good Practice.
The modified code should look like
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char mattsentence[51] = {0}; //always initalize local variables, here it's covering null termination , too.
fgets(mattsentence, 51, stdin); //fgets()
char mask[strlen(mattsentence) + 1]; // one more to store terminating '\0'
int i = 0, j = 0, k = 0;
j = strlen(mattsentence);
k = j;
for (i = 0; i < k; i++) // make use of k, don't call `strlen()` repeatedly
{
j = j - 1;
mask[i] = mattsentence[j];
printf("%c", mask[i]);
}
mask[i] = '\0'; // for proper string termination
printf("\n");
printf("%s\n", mask);
return 0; //added return statement
}
See changed code:
int main()
{
char mattsentence[51];
mattsentence[0] = '\0'; // initialization
gets(mattsentence);
char mask[strlen(mattsentence) + 1]; // +1 for string terminator '\0'
int i, j;
j = strlen(mattsentence);
for (i = 0; i < strlen(mattsentence); i++) // strlen of original string
{
j = j - 1;
mask[i] = mattsentence[j];
printf("%c", mask[i]);
}
mask[i] = '\0'; // for proper string termination
printf("\n");
printf("%s\n", mask);
}
There are several errors:
strlen() should be used to get length of string
for loop should be controlled according to input string, not output string
it is better to use fgets() instead of gets(): that way you can control how many character will be read from the input

Resources