Print with junk values,c - c

I'm having a problem and I can not figure out why.
In main I create 2 arrays of strings.
The function accepts 2 strings and creates a new array of the appropriate size according to the following requirement:
For example:
Array 1: aviv ,
Array 2: 12 ,
The new array: a12v12i12v
The new array must be exactly the size!
And then send the new array to main and main to print it.
I also print junk values.
I checked the size of the new array and it is the right size.
My code:
char* CreateString(char* str1, char* str2)
{
int length1, length2, length3 = 0;
int i,j, index_help = 0;
char *str3 = NULL;
length1 = strlen(str1);
length2 = strlen(str2);
for (i = 0; i < length1; i++) // Check the size of the new array
{
length3++;
if (i == (length1 - 1))
{
break;
}
for (j = 0; j < length2; j++)
{
length3++;
}
}
str3 = (char*)malloc(length3+1 * sizeof(char));
if (str3 == NULL)
{
printf("There is not enough memory space\n");
return 0;
}
for (i = 0; i < length1; i++) //Copying data
{
str3[index_help] = str1[i];
if (i == (length1 - 1))
{
break;
}
for (j = 0; j < length2; j++)
{
index_help++;
str3[index_help] = str2[j];
}
index_help++;
}
return str3;
}
int main()
{
char *str1 = NULL, *str2 = NULL,*str4=NULL;
int size1, size2,i;
printf("enter the size of string number 1:\n");
scanf("%d", &size1);
printf("enter the size of string number2 :\n");
scanf("%d", &size2);
str1 = (char*)malloc((size1 + 1) * sizeof(char));
if (str1 == NULL)
{
printf("There is not enough memory space\n");
return 0;
}
str2 = (char*)malloc((size2 + 1) * sizeof(char));
if (str2 == NULL)
{
printf("There is not enough memory space\n");
return 0;
}
printf("Enter a value for the first string (the size is:%d):\n", size1);
scanf("%s", str1);
printf("Enter a value for the second string (the size is:%d):\n", size2);
scanf("%s", str2);
str4 = CreateString(str1, str2);
printf("%s",str4);
printf("\n");
return 0;
}

The function should be declared like
char* CreateString( const char* str1, const char* str2);
because neither string str1 nor string str2 are changed in the function.
You have to append the result string with a terminating zero.
The length of the resulted string can be calculated simpler without using loops.
As the function strlen has the return type size_t then variables that accept the result of a function call should be also declared as having the type size_t instead of the type int.
The function can be implemented the following way as it is shown in the demonstrative program.
#include <stdio.h>
#include <string.h>
char * CreateString(const char *s1, const char *s2)
{
size_t n1 = strlen(s1);
size_t n2 = strlen(s2);
size_t n3 = n1 == 0 ? 0 : n1 + (n1 - 1) * n2;
char *s3 = ( char * )malloc(n3 + 1);
if (s3)
{
if (n2 == 0)
{
strcpy(s3, s1);
}
else
{
char *p = s3;
while (*s1)
{
*p++ = *s1++;
if (*s1)
{
strcpy(p, s2);
p += n2;
}
}
*p = '\0';
}
}
return s3;
}
int main( void )
{
char *p = CreateString("aviv", "12");
printf("\"%s\"\n", p);
free(p);
p = CreateString("", "12");
printf("\"%s\"\n", p);
free(p);
p = CreateString("a", "12");
printf("\"%s\"\n", p);
free(p);
p = CreateString("av", "12");
printf("\"%s\"\n", p);
free(p);
p = CreateString("av", "");
printf("\"%s\"\n", p);
free(p);
return 0;
}
The program output is
"a12v12i12v"
""
"a"
"a12v"
"av"

Related

Not getting output from string array function in c

I was making a split function in C to use its return value in some programs. But when I checked its value using printf, I discovered that there are some errors but I was unable to fix them myself. I fixed most of the errors I could.
The code I wrote is:
#include <stdio.h>
#include <string.h>
char **split(char *token, char *delimiter, int *a[], int *size_of_a) {
int i = 0;
char **final_result;
char *str = strtok(token, delimiter);
while (str != NULL) {
*a[i] = strlen(str); //maybe one of the errors but I don't know how to fix it
//even after removing a[i] by backslash and changing it in loop and main, there is still no output received in main
getch();
for (int j = 0; j < *a[i]; j++) {
final_result[i][j] = str[j];
}
str = strtok(NULL, delimiter);
i++;
}
*size_of_a = i;
return final_result;
}
int main() {
char *parameter_1;
char *parameter_2;
int *size_1;
int size_2;
printf("Enter the token: ");
scanf("%s", &parameter_1);
printf("\nEnter the delimiter: ");
scanf("%s", &parameter_2);
char **result_2 = split(parameter_1, parameter_2, &size_1, &size_2);
printf("\nThe result is:");
for (int x = 0; x < size_2; x++) {
printf('\n');
for (int y = 0; y < size_1[x]; y++) {
printf("%c", result_2[x][y]);
}
}
getch();
return 0;
}
How can I fix the output error?
There are multiple problems in the code:
You do not allocate space for the array of pointers: final_result is uninitialized, storing anything via dereferencing it has undefined behavior, most likely a segmentation fault.
You should use strcpn() and strspn() to compute the number of tokens, allocate the array with or without an extra slot for a NULL terminator and perform a second phase splitting the tokens and storing the pointers to the array. You might want to store copies of the tokens to avoid modifying the original string that may be constant or go out of scope.
printf('\n'); is invalid: you must pass a string, not a character constant.
scanf("%s", &parameter_1); also has undefined behavior: you pass the address of a pointer instead of a pointer to an array of char.
Here is a modified version:
#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef _MSC_VER
// define POSIX function strndup if not available
char *strndup(const char *s, size_t n) {
size_t len;
for (len = 0; len < n && s[len]; len++)
continue;
char *ptr = malloc(len + 1);
if (ptr) {
memcpy(ptr, s, len);
ptr[len] = '\0';
}
return ptr;
}
#endif
char **split(const char *str, const char *delimiters, int **a, int *size_of_a) {
int i, count, len;
char **final_result;
const char *p;
// phase 1: count the number of tokens
p = str + strspn(str, delimiters);
for (count = 0; *p; count++) {
p += strcspn(p, delimiters);
p += strspn(p, delimiters);
}
// phase 2: allocate the arrays
final_result = calloc(sizeof(*final_result), count + 1);
if (a) {
*a = calloc(sizeof(**a), count);
}
if (size_of_a) {
*size_of_a = count;
}
// phase 3: copy the tokens
p = str;
for (i = 0; i < count; i++) {
p += strspn(p, delimiters); // skip the delimiters
len = strcspn(p, delimiters); // count the token length
if (a) {
(*a)[i] = len;
}
final_result[i] = strndup(p, len); // duplicate the token
p += len;
}
final_result[count] = 0;
return final_result;
}
// read and discard the rest of the user input line
int flush_input(void) {
int c;
while ((c = getchar()) != EOF && c != '\n')
continue;
return c;
}
int main() {
char buf[256];
char delimiters[20];
printf("Enter the string: ");
if (scanf("%255[^\n]", buf) != 1)
return 1;
flush_input();
printf("\nEnter the delimiters: ");
if (scanf("%19[^\n]", delimiters) != 1)
return 1;
flush_input();
int *sizes;
int count;
char **array = split(buf, delimiters, &sizes, &count);
printf("\nThe result is:\n");
for (int x = 0; x < count; x++) {
for (int y = 0; y < sizes[x]; y++) {
putchar(array[x][y]);
}
printf("\n");
}
getchar();
return 0;
}

How can I concatenate characters to a string in C?

It's an exercise where I have to build a function which returns a string called "secret identity" composed with your birth date, your name and your mother's name (for example, if "02/12/2007", "LUCY TOLKIEN" and "JENNIFER" it returns "20070212LT*J") but I'm struggling to concatenate the characters (like "L" and "T" of "LUCY TOLKIEN") to the string called "secret identity". I hope I could explain it well.
There's what I did by far:
int length(char * s) {
int i, n = 0;
for (i = 0; *(s + i) != '\0'; i++) {
n++;
}
return n;
}
void concatenate(char * s, char * t) {
int i = 0;
int j;
while (*(s+i) != '\0') {
i++;
}
for (j = 0; *(t+i) != '\0'; j++) {
*(s + i) = *(t + j);
i++;
}
*(s + i + 1) = '\0';
}
void copy(char * dest, char * orig) {
int i;
for (i = 0; *(orig + i) != '\0'; i++) {
*(dest + i) = *(orig + i);
}
*(dest + i) = '\0';
}
void geraIdentidade(void) {
char * ident;
int lname, ldate, lmom;
char name[80];
printf("Name: ");
scanf(" %[^\n]s", name);
lname = length(name);
char date[11];
printf("Date: ");
scanf(" %[^\n]s", date);
ldate = length(date);
char mom[20];
printf("Name (mom): ");
scanf(" %[^\n]s", mom);
lmom = length(mom);
char day[3], month[3], year[5];
int i, j, k;
for (i = 0; date[i] != '/'; i++) {
day[i] = date[i];
day[i + 1] = '\0';
}
for (j = 3, i = 0; date[j] != '/'; j++, i++) {
month[i] = date[j];
month[i + 1] = '\0';
}
for (k = 6, i = 0; k <= 9; k++, i++) {
year[i] = date[k];
year[i + 1] = '\0';
}
ident = (char*)malloc((lmom + ldate + lname) * sizeof(char)); //change lenght
if (ident != NULL) {
copy(ident, year);
concatenate(ident, month);
concatenate(ident, day);
}
else {
return NULL;
}
printf("%s\n", ident);
}
int main(void) {
geraIdentidade();
return 0;
}
For my opinion, 3 functions in your code:
int length(char * s)
void concatenate(char * s, char * t)
void copy(char * dest, char * orig)
You can make the code easier to do when you use some C standard functions in <string.h>:
size_t strlen(const char *s); // for length
char *strcpy(char *dest, const char *src); // for copy
char *strcat(char *dest, const char *src); // for concatenation
When you want to concatenate string and character, you just need to convert character to string by adding the \0 character to the character you want to concatenate. For example, if you want to concatenate T to string 20070212L:
#include <stdio.h>
#include <string.h>
int main()
{
char str[11] = "20070212L";
char ch[2] = "\0";
ch[0] = 'T';
strcat(str, ch);
printf("str = %s", str);
return 0;
}
The output:
str = 20070212LT

Saving numbers (sequence of digits) from a string in an array of pointers to a char

I am supposed to save every sequence of digits from a string in an array of chars , this is what i tried:
#include<stdio.h>
#include<ctype.h>
#include<string.h>
int check_number(char *s) {
for (; *s; ++s) {
if (!isdigit(*s))
return 0;
}
return 1;
}
void int_in_string(char *s, char **ar, int MaxCap) {
char temp[100];
int index = 0;
int i = 0;
for (; *s; s++) {
if (index == MaxCap) {
break;
}
if (isdigit(*s)) {
temp[i++] = *s;
}
if (*s == ' ' && check_number(temp)) {
ar[index++] = temp;
memset(temp, '\0', i);
i = 0;
}
}
if (index == 0) {
printf("no numbers in string");
}
for (int i = 0; i < index; i++)
printf(" %s \n", ar[i]);
}
but this code only prints several newlines , can someone explain me what i do wrong?
Some issues:
ar[index++]=temp;
This is just storing the same value (the address of temp) over and over. What you need to do is copy the string into the array.
Also, you need to terminate the string temp with '\0'. You handle this in all but the first string with memset(temp, '\0', i); However, since local variables are not initialized, you need to do it:
char temp[100] = {0}
Or, you can remove the initialization and the memset by just adding the EOS:
temp[i] = '\0';
Lastly, since you declare the original array as
char * ar[10];
You are not allocating any space for the strings. The simplest way to handle that is with strdup.
void int_in_string(char *s, char **ar, int MaxCap)
{
char temp[100];
int index = 0;
int i = 0;
for (; *s; s++) {
if (isdigit(*s)) {
temp[i++] = *s;
// Need to avoid buffer overflow
if (i == sizeof(temp)) {
i = 0;
}
}
if (isspace(*s)) {
temp[i] = '\0';
// strdup will allocate memory for the string, then copy it
ar[index++] = strdup(temp);
// if (NULL == ar[index-1]) TODO: Handle no memory error
i = 0;
if (index == MaxCap) {
break;
}
}
}
if (index == 0) {
printf("no numbers in string");
}
for (int i = 0; i < index; i++) {
printf(" %s \n", ar[i]);
// free the mem from strdup
free(ar[i]);
}
}
I believe some systems may not have strdup(). If not, it can be easily replicated:
char * my_strdup(const char *src)
{
if (src == NULL) return NULL;
char *dest = malloc(strlen(src) + 1);
if (dest == NULL) return NULL;
strcpy(dest, src);
return dest;
}

Reversing String in C for loop error

I have an array of strings and am trying to reverse each string in the array to see if that string is a palindrome. I am using a for loop to increment an int i (the index). However after the I call the reverse function, the value of i becomes some really large number and I cant figure out why this is happening.
#include <stdio.h>
#include <string.h>
void revString(char *dest, const char *source);
int main() {
const char *strs[] = {
"racecar",
"radar",
"hello",
"world"
};
int i;
char res[] = "";
for (i = 0; i < strlen(*strs); i++) {
printf("i is %d\n", i);
revString(&res[0], strs[i]); //reversing string
printf("i is now %d\n", i);
//comparing string and reversed string
if (strcmp(res, strs[i]) == 0) {
printf("Is a palindrome");
} else {
printf("Not a palindrome");
}
}
return 0;
}
void revString(char *dest, const char *source) {
printf("%s\n", source);
int len = strlen(source);
printf("%d\n", len);
const char *p;
char s;
for (p = (source + (len - 1)); p >= source; p--) {
s = *p;
*(dest) = s;
dest += 1;
}
*dest = '\0';
}
This is the output showing the value of i before and after the revString function is called.
i is 0
i is now 1667588961
Illegal instruction: 4
There are multiple problems in your code:
You pass a destination array char res[] = ""; that is much too small for the strings you want to reverse. It's size is 1. This causes buffer overflow, resulting in undefined behavior.
Use char res[20]; instead.
You enumerate the array of string with an incorrect upper bound. Use this instead:
for (i = 0; i < sizeof(strs) / sizeof(*strs); i++)
The termination test for the loop in revString() is incorrect too: decrementing p when is equal to source has undefined behavior, although it is unlikely to have an consequences. You can simplify this function this way:
void revString(char *dest, const char *source) {
size_t len = strlen(source);
for (size_t i = 0; i < len; i++) {
dest[i] = source[len - i - 1];
}
dest[len] = '\0';
}
Here is the resulting code:
#include <stdio.h>
#include <string.h>
void revString(char *dest, const char *source) {
size_t len = strlen(source);
for (size_t i = 0; i < len; i++) {
dest[i] = source[len - i - 1];
}
dest[len] = '\0';
}
int main(void) {
const char *strs[] = { "racecar", "radar", "hello", "world" };
char res[20];
for (size_t i = 0; i < sizeof(strs) / sizeof(*strs); i++) {
revString(res, strs[i]);
//comparing string and reversed string
if (strcmp(res, strs[i]) == 0) {
printf("Is a palindrome\n");
} else {
printf("Not a palindrome\n");
}
}
return 0;
}
Here is Final Code with some change
#include <stdio.h>
#include <string.h>
void revString(char* dest, const char* source);
int main(){
const char* strs[] = {
"racecar",
"radar",
"hello",
"world"
};
static int i;
char res[] = "";
int length = (int) sizeof(strs)/sizeof(char*);
for(i = 0; i < length; i++)
{
printf("i is %d\n", i);
revString(&res[0], strs[i]); //reversing string
printf("i is now %d\n", i);
//comparing string and reversed string
if(strcmp(res, strs[i]) == 0){
printf("Is a palindrome");
}else{
printf("Not a palindrome");
}
}
return 0;
}
void revString(char* dest, const char* source){
printf("%s\n", source);
int len = (int) strlen(source);
printf("%d\n", len);
const char* p;
char s;
for(p = (source + (len - 1)); p >= source; p--){
s = *p;
*(dest) = s;
dest += 1;
}
*dest = '\0';
}
Change 1 :-
int i; to static int i; (Reason:- i is local variable you are calling
function so when function call the value of i will remove and after
that it will assign garbage value.)
change 2 :-
strlen(*strs) to length of array (because strlen(*strs) will give the
length of first string)

Number of times one string occurs within another in C

I have written a function that uses the strstr() function to determine if string2 has any matches in string1. This works fine (I also convert both strings to lower case so that I can do a case-insensitive match.). However, strstr() only finds the first time the match occurs. Is there a way to use it to find each time a match occurs? For example:
string1[] = "ABCDEFABC";
string2[] = "ABC";
Would return 0 as a match is found in position 0, and 6 as it's found again in position 6?
Here's the original function as written (including call to function in main):
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char *strstrnc(const char *str1, const char *str2);
int main()
{
char buf1[80],buf2[80];
printf("Enter the first string to be compared: ");
gets(buf1);
printf("Enter the second string to be compared: ");
gets(buf2);
strstrnc(buf1,buf2);
return 0;
}
char *strstrnc(const char *buf1, const char *buf2)
{
char *p1, *ptr1, *p2, *ptr2, *loc;
int ctr;
ptr1 = malloc(80 * sizeof(char));
ptr2 = malloc(80 * sizeof(char));
p1 = ptr1;
p2 = ptr2;
for (ctr = 0; ctr < strlen(buf1);ctr++)
{
*p1++ = tolower(buf1[ctr]);
}
*p1 = '\0';
for (ctr = 0; ctr < strlen(buf2);ctr++)
{
*p2++ = tolower(buf2[ctr]);
}
*p2 = '\0';
printf("The new first string is %s.\n", ptr1);
printf("The new first string is %s.\n", ptr2);
loc = strstr(ptr1,ptr2);
if (loc == NULL)
{
printf("No match was found!\n");
}
else
{
printf("%s was found at position %ld.\n", ptr2, loc-ptr1);
}
return loc;
}
Given
char string1[] = "ABCDEFABC";
char string2[] = "ABC";
strstr(string1, string2) will return a pointer to the first element of string1.
Would return 0 as a match is found in position 0, and 6 as it's found again in position 6?
In order to check for multiple occurrences of string2 in string1, you'll have to call strstr multiple times with an offset from string1. E.g.
char* found = strstr(string1, string2);
while ( found != NULL )
{
// Search for string2 after applying an offset.
int offset = 1;
found = strstr(found+offset, string2);
}
I think this is what you need:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main(void){
char string1[] = "ABCDABCEFABC";
char string2[] = "ABC";
char *s1, *s2, *s3;
size_t lenstring1 = strlen(string1);
size_t lenstring2 = strlen(string2);
if (lenstring2 < 1){
printf("There is no substring found"); /* or what ever */
exit(1);
}
size_t i=0,j=0;
int found=0;
s1 = string1;
s2 = string2;
for(i = 0; i < lenstring1; i++){
if(*s1 == *s2){
s3 = s1;
for(j = 0;j < lenstring2;j++){
if(*s3 == *s2){
s3++;s2++;
}else{
break;
}
}
s2 = string2;
if(j == strlen(string2)){
found = 1;
printf("%s found at index : %zu\n",string2,i+1);
}
}
s1++;
}
if(found == 0){
printf("No match Found");
}
return 0;
}
Output:
ABC found at index : 1
ABC found at index : 5
ABC found at index : 10
If the string2 is empty you will get:
There is no substring found

Resources