Reputation: 77
For C++ - I can add each char
to each index in string
array:
string *x=new string[10];
x[0] += "a";
x[0] += "b";
x[0] += "c";
x[1] += "x";
x[1] += "y";
x[1] += "z";
cout << "x[0]=" << x[0] << endl; // would be "abc"
cout << "x[1]=" << x[1] << endl; // would be "xyz"
How can I do same functionality in C? I have buff2
pointer to a char
array and am trying to add char
value from each index of buf
. I keep getting weird values when I print out buff2
value.
char buf[255];
char *buff2;
int i=0, count=0;
buff2=(char*)malloc(512*sizeof(char));
while((n = read(fd, buf, sizeof(buf[g]))) > 0){
for(i=0; i<n; i++){
if(buf[i] == '\n'){
l++;
count2++;
}
else
{
buff2[count2]+=buf[i];
}
}
Upvotes: 2
Views: 135
Reputation: 173
Here is a simple example if you do not want to use strcat
. This is a minimal example to demonstrate how one could concatenate strings, things like reallocation of memory have not been implemented.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char buf[30] = "LOREM \n IPSUM DOLOR SIT AMET\0";
char *buff2;
int i = 0, n = 30;
buff2 = (char*)malloc(512 * sizeof(char));
//set first element of buff2 to be terminating null char
buff2[0] = '\0';
for(i = 0; i < n; i++) {
if(buf[i] != '\n') {
buff2[i + 1] = '\0'; // shift terminating null char forward
buff2[i] = buf[i];
} else {
buff2[i + 1] = '\0'; // shift terminating null char forward
buff2[i] = 'n';
}
}
printf("%s\n",buff2);
return EXIT_SUCCESS;
}
It replaces newlines with an "n" character; you can change this if you want. Of course, you want to be careful only to address elements which have actually been allocated. Does not include function to read from file because we don't have the file; this is easily implemented. I suggest you look into fgetc
.
Upvotes: -1
Reputation: 32586
There are several problems in your C code
buff[0]
buff2[count2]+=buf[i];
always modify the same buff2[count2]
until a newline because you do not increase buff2 in that case but only when reading a newline, are you sure you want that ?string *x=new string[10];
can be in C
char ** x = calloc(10, sizeof(char *));
I use calloc to initialize with null pointers
and an equivalent of :
x[0] += "a";
can be
strCat(&x[0], "a");
with:
char * const strCat(char ** p, const char * s)
{
if (s != NULL) {
if (*p == NULL)
*p = strdup(s);
else {
size_t len = strlen(*p);
*p = realloc(*p, len + strlen(s) + 1); /* may be detect realloc returns NULL on error */
strcpy(*p + len, s);
}
}
return *p;
}
So for instance :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char * const strCat(char ** p, const char * s)
{
if (s != NULL) {
if (*p == NULL)
*p = strdup(s);
else {
size_t len = strlen(*p);
*p = realloc(*p, len + strlen(s) + 1); /* may be detect realloc returns NULL on error */
strcpy(*p + len, s);
}
}
return *p;
}
int main()
{
char ** x = calloc(10, sizeof(char *));
strCat(&x[0], "a");
strCat(&x[0], "b");
strCat(&x[0], "c");
strCat(&x[1], "x");
strCat(&x[1], "y");
strCat(&x[1], "z");
printf("x[0]=%s\n", x[0]);
printf("x[1]=%s\n", x[1]);
free(x[0]);
free(x[1]);
free(x);
return 0;
}
Compilation and execution:
% gcc -Wall a.c
% ./a.out
x[0]=abc
x[1]=xyz
%
Running under valgrind:
% valgrind ./a.out
==113490== Memcheck, a memory error detector
==113490== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==113490== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==113490== Command: ./a.out
==113490==
x[0]=abc
x[1]=xyz
==113490==
==113490== HEAP SUMMARY:
==113490== in use at exit: 0 bytes in 0 blocks
==113490== total heap usage: 7 allocs, 7 frees, 98 bytes allocated
==113490==
==113490== All heap blocks were freed -- no leaks are possible
==113490==
==113490== For counts of detected and suppressed errors, rerun with: -v
==113490== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
%
Note however each time you concatenate a new string it is needed to go through the current string to know its length, this is not done by std::string
whose knows the used length whatever the way for that, as this is the case in the answer of KamilCuk
Upvotes: 5
Reputation: 140970
How can I do same functionality in C?
First implement/invent a "string".
After that you can implement the functionality. Remember about proper error handling. I just used abort()
for brevity below, in normal code destructors should be run.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct string {
char *begin;
char *end;
size_t free;
} string;
void string_init(string *t) {
t->begin = t->end = NULL;
t->free = 0;
}
void string_fini(string *t) {
free(t->begin);
}
// iadd convention from python
int string_iadd_cstr(string *t, const char *str) {
const size_t addlen = strlen(str);
if (t->free < addlen + 1) {
const size_t curlen = t->end - t->begin;
const size_t newlen = curlen + 1 + addlen;
void *tmp = realloc(t->begin, newlen);
if (tmp == NULL) {
return -1;
}
t->begin = tmp;
t->end = t->begin + curlen;
t->free = newlen - curlen;
}
memcpy(t->end, str, addlen + 1);
t->end += addlen;
t->free -= addlen;
return 0;
}
int string_print(string *t) {
return printf("%s", t->begin);
}
int main() {
// string *x=new string[10];
string *x = malloc(10 * sizeof(*x));
if (x == NULL) abort();
for (size_t i = 0; i < 10; ++i) {
string_init(&x[i]);
}
if (string_iadd_cstr(&x[0], "a")) abort();
if (string_iadd_cstr(&x[0], "b")) abort();
if (string_iadd_cstr(&x[0], "c")) abort();
if (string_iadd_cstr(&x[1], "x")) abort();
if (string_iadd_cstr(&x[1], "y")) abort();
if (string_iadd_cstr(&x[1], "z")) abort();
// cout << "x[0]=" << x[0] << endl;
printf("%s", "x[0]=");
string_print(&x[0]);
printf("\n");
fflush(stdout);
// cout << "x[1]=" << x[1] << endl;
printf("%s", "x[1]=");
string_print(&x[1]);
printf("\n");
fflush(stdout);
// run destructors
for (size_t i = 0; i < 10; ++i) {
string_fini(&x[i]);
}
free(x);
}
Upvotes: 1