I'm having issues getting the desired behaviour out of my code. I'm new to the C language (although I usually program in C++ so I'm sort of familiar), and I'm unsure where to go with my issue. In the below code, when attempting to populate the 2 strings with the contents of the "input" string passed to the function, the result is that the memory locations are passed to the 2 strings, meaning when I perform modifications on the individual strings, the original data is edited... I want to have it such that the initial data is copied to the new memory locations allocated to the new strings.
bool interpretInput(char *input)
{
char *name = malloc(MAX_NAME_SIZE / 2);
char *surname = malloc(MAX_NAME_SIZE / 2);
if (name == NULL | surname == NULL)
{
return 1;
}
int length = (int) strlen(input);
if ((length > 0) && (input[length - 1] == '\n')) input[length - 1] = '\0';
if (surname = strpbrk(input, " "))
{
int sLength = (int) strlen(surname);
for (int i = 0; i < sLength; i++)
{
surname[i] = surname[i + 1];
}
length = (int) strlen(input);
for (int i = 0; i <= length - sLength; i++)
{
name[i] = input[i];
}
length = (int) strlen(name);
sLength = (int) strlen(surname);
printf("Name: %s length: %d \n", name, length);
printf("Surname: %s length: %d \n", surname, sLength);
}
else
{
printf("Name length: %d", length);
}
return 0;
}
EDIT: I, effectively, want to populate one array with the values at each increment of another array, without using strcpy.
I think you want strcpy(char* dest, char* src). Dereferencing a char* will simply yield you the first char in the string.
#include <stdio.h>
int main()
{
char* test = "hello world";
char* test2 = malloc(11*sizeof(char));
strcpy(test2, test);
printf("%s\n", test);
printf("%s\n", test2);
test2[5] = '_';
printf("%s\n", test);
printf("%s\n", test2);
printf("%c\n", *test);
free(test2);
}
spits out
hello world
hello world
hello world
hello_world
h
Related
I am having trouble with the very last line in my function, where I am stilly learning the basics of C. I have the signature of this function given and am tasked to write a function to concatenate two strings. The commented line outputs the correct result.
#include <stdio.h>
#include <stdlib.h>
// 1) len = dst-len + max_dst_len
int strlcat(char *dst, const char *src, int max_dst_len) {
int len = 0;
while (dst[len] != '\0') {
len++;
}
int total_len = len + max_dst_len;
char *new_str = malloc(sizeof(char) * total_len);
for (int i = 0; i < len; i++) {
new_str[i] = dst[i];
}
for (int i = len; i < total_len; i++) {
new_str[i] = src[i - len];
}
new_str[total_len] = '\0';
//printf("%s <--\n", new_str);
dst = *new_str;
return total_len;
}
int main() {
char test1[] = "dst";
char test1src[] = "src";
printf("%s\n", test1);
printf("%d\n", strlcat(test1, test1src, 10));
printf("%s\n", test1);
}
You should not be adding max_dst_len to the length of dst. max_dst_len is the amount of memory that's already allocated in dst, you need to ensure that the concatenated string doesn't exceed this length.
So you need to subtract len from max_dst_len, and also subtract 1 to allow room for the null byte. This will tell you the maximum number of bytes you can copy from src to the end of dst.
In your main() code, you need to declare test1 to be at least 10 bytes if you pass 10 as the max_dst_len argument. When you omit the size in the array declaration, it sizes the array just big enough to hold the string you use to initialize it. It's best to use sizeof test1 as this argument, to ensure that it's correct for the string you're concatenating to.
#include <stdio.h>
int strlcat(char *dst, const char *src, int max_dst_len) {
int len = 0;
while (dst[len] != '\0') {
len++;
}
int len_to_copy = max_dst_len - len - 1;
int i;
for (i = 0; i < len_to_copy && src[i] != '\0'; i++) {
dst[len+i] = src[i];
}
dst[i] = '\0';
//printf("%s <--\n", new_str);
return i + len;
}
int main() {
char test1[6] = "dst";
char test1src[] = "src";
printf("%s\n", test1);
printf("%d\n", strlcat(test1, test1src, sizeof test1));
printf("%s\n", test1);
}
I have a function that gets char * and I want to print the additional value in each interaction
For example:
hello
h
he
hel
hell
hello
The problem is that I have a memory impairment and writing
Exception thrown at 0x7B18F791 (ucrtbased.dll) in workhome4.exe: 0xC0000005: Access violation reading location 0x00000069.
void addSpaceCheck(char* word)
{
char* stringOne = malloc(sizeof(char) * 1024);
for (int i = 0; i < strlen(word); i++) {
strcat(stringOne, word[i]);
printf("%s", stringOne);
}
}
}
strcat(stringOne, word[i]); causes the problem in this case. strcat expects a NUL terminated string. stringOne is allocated but does not contain any useful data. Optionally, you could use calloc() to zero out the allocated block of memory. In any case, strcat(stringOne, word[i]); will not do what you think because the second argument is a char.
You could do this:
void addSpaceCheck(char* word)
{
char* stringOne = malloc(sizeof(char) * 1024);
for (int i = 0; i < strlen(word) - 1; i++) {
stringOne[i] = word[i];
stringOne[i + 1] = '\0';
printf("%s", stringOne);
}
}
}
You can't use strcat() without adding a string terminator first.
Nor can you hope that strcat() can add a single character like that.
Instead I suggest
for (size_t i = 0; i < strlen(word); i++) {
stringOne[i] = word[i];
stringOne[i+1] = '\0';
printf("%s ", stringOne);
}
This will ouput
H He Hel Hell Hello
strcat requires char * as second parameter not char
if you want to use strcat you need to pass a valid C string as second parameter
void addSpaceCheck1(char* word)
{
size_t length = strlen(word);
char* stringOne = malloc(length + 1);
for (size_t i = 0; i < length; i++)
{
strcat(stringOne, (char[]){word[i], 0});
printf("%s ", stringOne);
}
free(stringOne);
}
But it makes a little sense to use this very heavy function. You can simply assign the char and terminate the string.
void addSpaceCheck(char* word)
{
size_t length = strlen(word);
char* stringOne = malloc(length + 1);
for(size_t index = 0; index < length; index++)
{
stringOne[index] = word[index];
stringOne[index + 1] = 0;
printf("%s\n", stringOne);
}
free(stringOne);
}
If the purpose of the function is only to print, you don't need another string to do it.
You can use printf directly with the format %.*s that allows you to specify the (maximum) number of characters printed:
void addSpaceCheck(const char *word) // const if not modified
{
for (int i = 0; word[i] != '\0'; ++i)
{
printf("%.*s\n", i+1, word);
}
}
I have a program that has to count the number of duplicate characters in a string. For example "aaabcc" should return "a3b1c2" and "aaabcccc..a" should return "a3b1c4.2a1". I am currently using sprintf to concatenate the string and numbers like this: sprintf(s, "%s%c%d", s, prev, count);, where s is the string containing the result. But that causes an error since I am using "s" as an input and also as the destination. Is there some way around this?
This is my code right now:
char *s = (char *)malloc(sizeof(char) * 100);
char prev = argv[1][0];
if(isdigit(prev)!=0){
printf("%s","ERROR");
return 0;
}
int count = 1;
for(int i=1; i<strlen(argv[1]); i++){
if(isdigit(argv[1][i])!=0){
printf("%s","ERROR");
return 0;
}
//check if same as previous letter
if(prev==argv[1][i]){
count++;
}else{
//add letter and count to string
//problem
sprintf(s, "%s%c%d", s, prev, count);
count = 1;
}
//update prev
prev=argv[1][i];
}
//add it to string
//problem
sprintf(s, "%s%c%d", s, prev, count);
//check if result is smaller than input
if(strlen(s) > strlen(argv[1])){
printf("%s\n", argv[1]);
}else{
printf("%s\n", s);
}
free(s);
Use a different buffer for sprintf(), then concatenate to s with strcat().
Make sure you initialize s to an empty string after allocating it.
Instead of allocating a hard-coded size for s, allocate a string big enough for the worst case (every character repeated just once, so it's a1b1c1...).
temp can be a short, fixed-size string, since it just has to hold the length of one run.
char *s = malloc(strlen(argv[1]) * 2 + 1);
s[0] = '\0';
char temp[20];
char prev = argv[1][0];
if(isdigit(prev)!=0){
printf("%s","ERROR");
return 0;
}
int count = 1;
for(int i=1; i<strlen(argv[1]); i++){
if(isdigit(argv[1][i])!=0){
printf("%s","ERROR");
return 0;
}
//check if same as previous letter
if(prev==argv[1][i]){
count++;
}else{
//add letter and count to string
sprintf(temp, "%c%d", prev, count);
strcat(s, temp);
count = 1;
}
//update prev
prev=argv[1][i];
}
//add it to string
sprintf(temp, "%s%c%d", prev, count);
strcat(s, temp);
//check if result is smaller than input
if(strlen(s) > strlen(argv[1])){
printf("%s\n", argv[1]);
}else{
printf("%s\n", s);
}
free(s);
The advice in the comments and other answers are giving you good guidance on how manage the strings that you are dynamically allocating with malloc. But you can simplify your entire program without ever allocating a string and without using sprintf.
Consider this:
int lastChar = '\0';
int count = 0;
const char* arg = argv[1];
int isError = 0;
if (argc < 2) {
isError = 1;
}
while (*arg & !isError) { // scan argv[1] for digits
isError = isdigit(*arg);
arg++;
}
arg = argv[1]; // reset arg back to beginning of argv[1]
while (*arg && !isError) {
if (lastChar == *arg) {
count++;
}
else {
if (count > 0) {
printf("%c%d", lastChar, count);
}
lastChar = *arg;
count = 1;
}
arg++;
}
// print the last character being tracked or error message
if (isError) {
printf("ERROR");
}
else if (count > 0) {
printf("%c%d", lastChar, count);
}
printf("\n");
I am trying to compare strings received from the command line arguments without using the string library. I have created a function to compare char*'s and it works for strings I create in my program, but not on strings passed in the command line. Here is the code for reference.
#include <stdio.h>
int comparestr(char* a, char* b) {
printf("string 1 = %s, string 2 = %s\n", a, b);
int len_a =0, len_b=0;
while(*a) {
len_a++;
a++;
}
while(*b) {
len_b++;
b++;
}
printf("len a = %d, len b = %d\n", len_a, len_b);
if (len_a == len_b) {
for(int i=0; i<len_a; i++) {
if(*(a+i) != *(b+i)) {
return 0;
}
}
return 1;
}
else
return 0;
}
int main(int argc, char**argv) {
char* str1 = "hello";
char* str2 = "hello";
if(comparestr(str1,str2))
printf("Same string.\n");
else
printf("Different strings.\n");
if(comparestr(*(argv+1),"hell"))
printf("Same cl string.\n");
else
printf("Different cl strings.\n");
return 0;
}
Here is an example of the output.
./a.out hell hell
string 1 = hello, string 2 = hello
len a = 5, len b = 5
Same string.
string 1 = hell, string 2 = hell
len a = 4, len b = 4
Different cl strings.
The issue with your code is that you change the pointer by incrementing it when you try to get the length of the strings. Once you change the pointers, the pointers will not point to the base of your strings.
Instead of changing your pointer, make a copy of it, and use the copy instead to calculate the length of the string, that way you don't lose the base address of your strings.
New code with changes.
//Copy of the pointer, to change this instead and keep the original pointer address
char* ptr_a = a;
char* ptr_b = b;
int len_a =0, len_b=0;
while(*ptr_a) {
len_a++;
ptr_a++;
}
while(*ptr_b) {
len_b++;
ptr_b++;
}
The whole code.
#include <stdio.h>
int comparestr(char* a, char* b) {
printf("string 1 = %s, string 2 = %s\n", a, b);
//Copy of the pointer, to change this instead and keep the original pointer address
char* ptr_a = a;
char* ptr_b = b;
int len_a =0, len_b=0;
while(*ptr_a) {
len_a++;
ptr_a++;
}
while(*ptr_b) {
len_b++;
ptr_b++;
}
printf("len a = %d, len b = %d\n", len_a, len_b);
if (len_a == len_b) {
for(int i=0; i<len_a; i++) {
if(*(a+i) != *(b+i)) {
return 0;
}
}
return 1;
}
else
return 0;
}
int main(int argc, char**argv) {
char* str1 = "hello";
char* str2 = "hello";
if(comparestr(str1,str2))
printf("Same string.\n");
else
printf("Different strings.\n");
if(comparestr(*(argv+1),"hell"))
printf("Same cl string.\n");
else
printf("Different cl strings.\n");
return 0;
}
New Output
Command-line arguments: hell hell
string 1 = hello, string 2 = hello
len a = 5, len b = 5
Same string.
string 1 = hell, string 2 = hell
len a = 4, len b = 4
Same cl string.
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"