#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#define MAX_SIZE 20
void main()
{
int i, j;
char *str1, *str2, *str3, *str_mid;
bool **lcs1, **lcs2;
int len1, len2, len3, len_mid;
char *ch = (char*)malloc(sizeof(char) * 3);
str1 = (char*)malloc(sizeof(char)*MAX_SIZE); //applicatian
str2 = (char*)malloc(sizeof(char)*MAX_SIZE); //apiasn
str3 = (char*)malloc(sizeof(char)*MAX_SIZE); //apun
str_mid = (char*)malloc(sizeof(char)*MAX_SIZE); //apn
str_mid = "";
scanf("%s", str1);
scanf("%s", str2);
scanf("%s", str3);
len1 = strlen(str1);
len2 = strlen(str2);
len3 = strlen(str3);
//str2, str3 ->str_mid (lcs1)
lcs1 = (bool**)malloc(sizeof(bool*)*(len3 + 1));
for (i = 0; i < len3 + 1; i++)
lcs1[i] = (bool*)malloc(sizeof(bool)*(len2 + 1));
for (i = 0; i < len3 + 1; i++)
for (j = 0; j < len2 + 1; j++)
lcs1[i][j] = false;
for (i = 1; i < len3 + 1; i++)
for (j = 1; j < len2 + 1; j++)
if (str3[i-1] == str2[j-1])
lcs1[i][j] = true;
for (i = 1; i < len3 + 1; i++)
{
for (j = 1; j < len2 + 1; j++)
if (lcs1[i][j])
{
//<--- error
ch = str3[i - 1];
strcat(str_mid, ch);
//--->
break;
}
}
//printf("%s", str_mid);
//str_mid, str1 (lcs2)
}
In <--- error ---> part,
I want to concatenation str3[i-1] and str_mid but, str3[i-1] is character type.
So make temporary string is ch and do concatenate.
But, the access error is occurred.
How to make char to string or, how to concatenate char and string?
So long as MAX_SIZE is large enough that str_mid will be able to hold the extra character, you can use strcat() and a compound literal (for C99 or later):
strcat(str_mid, (char[2]){ str3[i - 1], '\0' });
Note that in your code, str3[i - 1] is a char, while you have declared ch as a pointer to char.
How to concatenate char and string
There is no need to call any library function at all, nor to dynamically allocate any memory.
Assuming str_mid is large enough just do:
{
size_t tmp_len = strlen(str_mid);
str_mid[tmp_len] = str3[i - 1];
str_mid[tmp_len + 1] = '\0';
}
To still have the feeling to use a function you might want to wrap the above code into a macro like this:
#define STRCATCHAR(s, c) \
do { \
assert(s != NULL); \
size_t tmp_len = strlen(s); \
(s)[tmp_len] = (c); \
(s)[tmp_len + 1] = '\0'; \
} while (0)
and use it like this:
STRCATCHAR(str_mid, str3[i - 1]);
To concatenate char and string (first char, then string) do:
const char* conc_char_string(const char ch, const char* str, int len) {
const char* out = malloc(len + 2); /* 1 char from ch, len chars from str, and zero character, totally len+2 */
out[0] = ch; /* copy the character */
strcpy(out+1, str); /* copy the string */
return out;
}
Here len should be strlen(str)
The statement str_mid = ""; assigns the address of costant string "" to pointer str_mid, which will cause segmentfault later. Use str_mid[0] = '\0'; instead.
In statement ch = str3[i - 1];, you are assigning char to char pointer, which will cause segmentfault.
If all you want is simply appending a character to the string, you can keep track of length of string, like this:
len_mid = strlen(str_mid);
for (i = 1; i < len3 + 1; i++)
{
for (j = 1; j < len2 + 1; j++)
if (lcs1[i][j])
{
str_mid[len_mid++] = str3[i - 1];
str_mid[len_mid] = '\0';
break;
}
}
First rule of the C-club, create your own string buffer, second rule of the C-club create your own string buffer.
Each programmer has it's own string buffer. Minimal requirement is :
#define STRINGSTRTSZ 256
typedef struct string
{
char *str;
size_t n;
size_t buf_sz;
}String,*pString;
pString new_string()
{
pString res;
res=malloc(sizeof(String)); ///i leave to you the error handling
res->bus_sz=STRINGSTRSZ;
res->n=0;
res->str=malloc(res->bus_sz);
}
char*concatbase(pString *string,char*s,size_t len)
{
if(len+1>=string->buf_sz-string->n)
{
res->buf_sz+=len+res->buf_sz;
char *tmp=realloc(string->str,res->buf_sz);
if(tmp)
string->str=tmp;
else
...
}
memcpy(string->str+string->n,s,len);
string->n+=len;
*(string->str+string->n)='\0';
return string->str;
}
#define concatNllPtr(string,nllptr) concatbase(string,nllptr,strlen(nllptr))
#define concatString(string,str2) concatbase(string,(str2)->str,(str2)->n)
End so on...
Related
I'm writing a function to rearrange a string's characters. I allocated the new string with malloc and initialize it, and then return it. But when I return it, it always only returns the first character.
I've tried printing the characters of the new string one by one and they print out correctly, but when I call the function, only the first character is returned. I can't figure out why. Any help would be appreciated!
Here's my code:
char * solution(char * s) {
int len = strlen(s);
int i;
int index = 0;
char *ans = (char *) malloc(sizeof(char) * (len + 1));
if (ans == NULL) {
fprintf(stderr, "Ran out of space in some function \n");
exit(1);
}
//char* ans = (char *) malloc(len + 1);
ans[len] = '\0';
for(i = 0; i < len/2; i++){
ans[index++] = s[i];
ans[index++] = s[len - i];
}
if(len % 2 == 1){
ans[index] = s[len/2];
}
return ans;
}
In the first iteration of this for loop
for(i = 0; i < len/2; i++){
ans[index++] = s[i];
ans[index++] = s[len - i];
}
the character ans[1] is set to s[len] (i is equal to 0 in the first iteration of the loop) that is to '\0'.
As a result you will get a string that contains only one character.
What you do is what you get.:)
It seems you mean
ans[index++] = s[len - i - 1];
Pay attention to that as the source string is not changed within the function then the function should be declared like
char * solution( const char * s );
The original declaration
char * solution(char * s);
means that the string will be changed in place.
If you want to change a string in place then the function can look the following way as shown in the demonstration program below.
#include <string.h>
#include <stdio.h>
char * solution( char *s )
{
size_t n = strlen( s );
for (size_t i = 1; i < n; i += 2)
{
char c = s[n - 1];
memmove( s + i + 1, s + i, n - i - 1);
s[i] = c;
}
return s;
}
int main( void )
{
char s[] = "0123456789";
puts( s );
puts( solution( s ) );
}
The program output is
0123456789
0918273645
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'm quite new to C and am trying to write a function, which will split a string into an array of strings at a specific delimiter. But strangely I can only write at the first index of my char** array of strings, which will be my result. For example if I want to split the following string "Hello;;world;;!" at ;; I get [ "Hello" ] instead of [ "Hello", "world", "!" ]. I can't find my mistake.
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "strings.h"
int split(char **dest, const char *src, const char *splitStr) {
char buffer[16384];
int counter = 0;
int len = strlen(splitStr);
int flag = 0;
int start = 0;
for (int i = 0; i < strlen(src); i++) {
flag = 0;
if (src[i] == splitStr[0]) {
for (int j = 1; j < len; j++) {
//check if all elements in delimiter are in string
if (src[i + j] == splitStr[j] && j != (len - 1)) {
continue;
}
else if(src[i + j] == splitStr[j] && j == (len - 1)) {
buffer[i] = '\0';
dest[counter] = malloc(sizeof(char) * (i - start + 1));
strncpy(dest[counter], buffer + start, (i - start));
start = i + (len-1)
flag = 1;
i += (len - 1);
counter++;
}
//if not break
else {
break;
}
}
}
if (i == (strlen(src) - 1)) {
buffer[i] = src[i];
buffer[i + 1] = '\0';
counter++;
break;
}
if (flag == 0) {
buffer[i] = src[i];
}
}
return counter;
}
A proper function call would look like this:
auto src = "Hello;;world;;!";
auto buffer = (char **)malloc(32);
int count = split(buffer, src, ";;");
The buffer should contain, all the splitted strings, more or less like this: [ "Hello", "world", "!" ].
Currently my result buffer looks like this in the debugger. It appears as only the first element is written into it.
There are multiple problems in your code:
you compute string lengths repeatedly, which may be very inefficient. Instead of testing i < strlen(src) you should write src[i] != '\0'.
your test for check a matching delimiter is too complicated. You should use strstr to locate the delimiter string in the remaining portion of the string.
strncpy does not do what you think: strncpy(dest[counter], buffer + start, (i - start)); should be replaced with memcpy(dest[counter], buffer + start, i - start); and you must set the null terminator explicitly: dest[counter][i - start] = '\0'; You should read why you should never use strncpy().
it is unclear why you use buffer at all.
Here is a modified version:
#include <stdlib.h>
#include <string.h>
/* if POSIX function strndup() is not defined on your system, use this */
char *strndup(const char *str, size_t n) {
size_t len;
for (len = 0; len < n && str[len] != '\0'; len++)
continue;
char *s = malloc(len + 1);
if (s != NULL) {
memcpy(s, str, len);
s[len] = '\0';
}
return s;
}
int split(char **dest, const char *src, const char *splitStr) {
const char *p = str;
const char *end;
int counter = 0;
size_t len = strlen(splitStr);
if (len == 0) {
/* special case */
while (*p != '\0') {
dest[counter++] = strndup(p++, 1);
}
} else {
while ((end = strstr(p, splitStr)) != NULL) {
dest[counter++] = strndup(p, end - p);
p = end + len;
}
dest[counter++] = strdup(p);
}
return counter;
}
First of all you are not updating the start variable after you have copied the first string.
For simple debugging I would recommend adding some printf statements to see what is going on.
Proper formatting is not to be underestimated to make the code easy to read and easier to debug.
Also it is not clear what the buffer is for, and I think you can do without it.
The tips in the comments are also good. Split the function into smaller pieces and structure your code so it is simple to read.
A suggestion is to write a function to find the index of the next split string and the end of the string. Then you can use that to get the index and length you need to copy.
Following is my code, I want to use pointer to pointer to store strings.
char **BlankWords(char word[]){
// take word 'lad' as an example
// length of it is 3
// fill in blank: _ad, l_d, la_, _lad, l_ad, la_d, lad_
// 3 + 4 = 7
// which means, length of 'lad' + (length of 'lad') + 1
int strLength = strlen(word);
char **blank_words = malloc(sizeof(char*) * (2 * strLength + 1));
assert(blank_words != NULL);
int i, j, k;
for (i = 0; i < strLength; i++){
// allocate memory for each length of the word
blank_words[i] = calloc(MAX_WORD_LENGTH, sizeof(char));
assert(blank_words[i] != NULL);
char temp[MAX_WORD_LENGTH];
strcpy(temp, word);
temp[strLength] = '\0';
temp[i] = '_';
blank_words[i] = temp;
// printf("%s\n", blank_words[0]);
}
for (j = strLength; j < (2 * strLength + 1); j++){
// allocate memory for each length of the word
blank_words[j] = calloc(MAX_WORD_LENGTH, sizeof(char));
assert(blank_words[j] != NULL);
char temp[MAX_WORD_LENGTH];
strcpy(temp, word);
temp[(strlen(temp) + 1)] = '\0';
for (k = (strLength - 1); k >= (j - strLength); k--){
if (k >= 0){
temp[k + 1] = temp[k]; // in order to insert '_' to the word, then the other letter move back one
}
}
temp[j - strLength] = '_'; // insert '_' to the word
blank_words[j] = temp;
}
return blank_words;
}
Following is the output, each row was overwritten after each loop, but in my opinion, each row cannot be overwritten, and may store a unique string.
blank_words[0]: lab_
blank_words[1]: lab_
blank_words[2]: lab_
blank_words[3]: lab_
blank_words[4]: lab_
blank_words[5]: lab_
blank_words[6]: lab_
I don't know why the previous data gets overwritten after each loop. In my opinion, the output should be:
blank_words[0]: _ab
blank_words[1]: l_b
blank_words[2]: la_
blank_words[3]: _lab
blank_words[4]: l_ab
blank_words[5]: la_b
blank_words[6]: lab_
As others have said, a local buffer disappears when its scope closes. Since the char** array points to buffers of that sort, the result is undefined behavior. You'll need to allocate the result strings with malloc.
Another tip: You can build the second set of strings by just moving the underscore rather than creating each from scratch. This is simpler:
#include <stdlib.h>
#include <string.h>
#include <assert.h>
void *safe_malloc(size_t n) {
void *r = malloc(n);
assert(r);
return r;
}
char *stralloc(char *s) {
return strcpy(safe_malloc((strlen(s) + 1) * sizeof(char)), s);
}
char **variations(char *s) {
int len = strlen(s), rp = 0;
char **r = safe_malloc((2 * len + 1) * sizeof *r);;
char buf[len + 2];
strcpy(buf, s); // Copy in case s is a read-only literal.
for (int i = 0; i < len; ++i) {
char t = buf[i]; // Remember the i'th char.
buf[i] = '_'; // Overwrite with _.
r[rp++] = stralloc(buf); // Capture a copy.
buf[i] = t; // Replace original char.
}
buf[0] = '_'; // Make the 1st char _.
strcpy(buf + 1, s); // Copy the rest after.
r[rp++] = stralloc(buf); // Capture a copy.
for (int i = 0; i < len; ++i) {
buf[i] = buf[i + 1]; // Overwrite _ with following char.
buf[i + 1] = '_'; // Move the _ up one position.
r[rp++] = stralloc(buf); // Capture a copy.
}
return r;
}
How can I split a const char * string in the fastest possible way.
char *inputStr="abcde";
char buff[500];
I would like to have in buffer the following formatted string, format of which must be:
IN('a','ab','abc','abcd','abcde')
I'm learning C and new to the language. I have no clue where to start on this splitting problem.
I don't think you can do this particularly "fast", it seems like it's quite heavily limited since it needs to iterate over the source string many times.
I'd do something like:
void permute(char *out, const char *in)
{
const size_t in_len = strlen(in);
char *put;
strcpy(out, "IN(");
put = out + 3;
for(i = 1; i < in_len; ++i)
{
if(i > 1)
*put++ = ',';
*put++ = '\'';
memcpy(put, in, i);
put += i;
*put++ = '\'';
}
*put++ = ')';
*put++ = '\0';
}
Note that this doesn't protect against buffer overrun in the output.
You could use strcpy, strcat/strncat and a simple loop:
#include <stdio.h>
#include <string.h>
int main(void) {
char* inputStr = "abcde";
char buff[500];
// start the formatted string:
strcpy(buff,"IN(");
int i, len = strlen(inputStr);
for (i = 0; i < len; ++i) {
strcat(buff, "'");
strncat(buff, inputStr, i + 1);
strcat(buff, "'");
// if it is not last token:
if (i != len - 1)
strcat(buff, ",");
}
// end the formatted string:
strcat(buff,")");
printf("%s", buff);
return 0;
}
outputs the desired IN('a','ab','abc','abcd','abcde')
To give you a start, consider the following code:
char buffer[64];
const char str[] = "abcde";
for (size_t i = 1; i <= strlen(str); ++i)
{
strncpy(buffer, str, i);
buffer[i] = '\0'; /* Make sure string is terminated */
printf("i = %lu, buffer = \"%s\"\n", i, buffer);
}
The above code should print
i = 1, buffer = "a"
i = 2, buffer = "ab"
i = 3, buffer = "abc"
i = 4, buffer = "abcd"
i = 5, buffer = "abcde"
If you are looking for something like this in C++:-
#include <iostream>
#include <string.h>
using namespace std;
int main() {
const char *inputStr = "abcde"; //const to remove warning of deprecated conversion
char buff[500];
int count = 0;
for (int i = 0; i < (int) strlen(inputStr); i++) { //cast it to int to remove
// warning of comparison between signed and unsigned
for (int j = 0; j <= i; j++) {
buff[count++] = inputStr[j];
}
buff[count++] = ',';
}
buff[--count] = '\0';
cout << buff;
return 0;
}
Output - a,ab,abc,abcd,abcde