Null terminating char pointer - c

I am completely newbie in C.
I am trying to do simple C function that will split string (char array).
The following code doesn't work properly because I don't know how to terminate char array in the array. There are to char pointers passed in function. One containing original constant char array to be split and other pointer is multidimensional array that will store each split part in separate char array.
Doing the function I encountered obviously lots of hustle, mainly due to my lack of C experience.
I think what I cannot achieve in this function is terminating individual array with '\0'.
Here is the code:
void splitNameCode(char *code, char *output);
void splitNameCode(char *code, char *output){
int OS = 0; //output string number
int loop;
size_t s = 1;
for (loop = 0; code[loop]; loop++){
if (code[loop] == ':'){
output[OS] = '\0'; // I want to terminate each array in the array
OS ++;
}else {
if (!output[OS]) {
strncpy(&output[OS], &code[loop], s);
}else {
strncat(&output[OS], &code[loop], s);
}
}
}
}
int main (int argc, const char * argv[]) {
char output[3][15];
char str[] = "andy:james:john:amy";
splitNameCode(str, *output);
for (int loop = 0; loop<4; loop++) {
printf("%s\n", output[loop]);
}
return 0;
}

Here is a working program for you. Let me know if you need any explanation.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
void splitNameCode(char *code, char **output) {
int i = 0;
char* token = strtok(code, ":");
while (token != NULL) {
output[i++] = token;
token = strtok(NULL, ":");
}
}
int main (int argc, const char *argv[]) {
char* output[4];
char input[] = "andy:james:john:amy";
splitNameCode(input, output);
for (int i = 0; i < 4; i++) {
printf("%s\n", output[i]);
}
return 0;
}

If I understand your intent correctly, you are trying to take a string like andy:james:john:amy and arrive at andy\0james\0john\0amy. If this is the case, then your code can be simplified significantly:
void splitNameCode(char *code, char *output){
int loop;
strncpy(code, output, strlen(code));
for (loop = 0; output[loop]; loop++){
if (output[loop] == ':'){
output[loop] = '\0'; // I want to terminate each array in the array
}
}
}

Related

What's wrong with my function? I have function that finds all common chars and concatenates them into one string

I have function that finds all common chars and concatenates into one string.
char* commonString(char* p1,char* p2)
{
char* res = "";
for (int k=0;k<strlen(p1);k++)
{
for (int h=0;h<strlen(p2);h++)
{
if (p1[k] == p2[h])
{
strcat(res,&p1[k]);
}
}
}
return res;
}
What's wrong with it? Can you review and help to fix it?
Example of I/O:
Example 00
Input: "padinton" && "paqefwtdjetyiytjneytjoeyjnejeyj"
Output:
Return Value: "padinto"
P.S. I also have function that removes all duplicated chars except the first ocurrence of it from strings.
This function works after removing them
The two main problems in your code are that you are not allocating space for the resulting string and you are using the strcat function inappropriately. Below is a brief implementation of what you are trying to achieve.
#include <stdlib.h>
#include <string.h>
char *commonString(char* p1,char* p2)
{
const size_t lenp1 = strlen(p1);
char *res = malloc(lenp1 + 1);
size_t j = 0;
for (size_t i = 0; i < lenp1; ++i)
if (strchr(p2, p1[i]))
res[j++] = p1[i];
res[j] = 0;
return res;
}
Important Note: The pointer returned by the malloc function must be checked against NULL before being dereferenced. It is omitted here for brevity.
There are so many issues in your code.
Not allocating memory,
Modifying string literals
returning local variables
etc etc.
Your function is also inefficient. You call strlen on every iteration, call strcat (which is very expensive) just to add 1 char.
This function does what you want with or without the duplicates.
#include <stdlib.h>
#include <stdio.h>
char *mystrnchr(const char *str, const char ch, size_t size)
{
char *result = NULL;
while(size--)
{
if(*str == ch)
{
result = (char *)str;
break;
}
str++;
}
return result;
}
char *mystrchr(const char *str, const char ch)
{
char *result = NULL;
while(*str)
{
if(*str == ch)
{
result = (char *)str;
break;
}
str++;
}
return result;
}
char* commonString(char *buff, const char* p1, const char* p2, int duplicates)
{
size_t size = 0;
char p1c;
while((p1c = *p1++))
{
if(!duplicates)
{
if(mystrnchr(buff, p1c, size))
{
continue;
}
}
if(mystrchr(p2, p1c))
{
buff[size++] = p1c;
}
}
buff[size] = 0;
return buff;
}
int main()
{
char result[23];
char *str1 = "paaaadiiiiinton";
char *str2 = "paqefwtdjetyiytjneytjoeyjnejeyj";
printf("%s\n", commonString(result, str1, str2, 0));
printf("%s\n", commonString(result, str1, str2, 1));
}
You can experiment with it yourself here: https://godbolt.org/z/qMnsfa
Here's a solution along those lines:
#include <stdio.h>
#include <string.h>
#define MAX_LENGTH 512
void removeDup(char *result, char *string)
{
for (int i = 0; i < strlen(string); i++)
{
char C[2] = { string[i], '\0' };
if (strstr(result, C) == NULL)
strcat(result, C);
}
}
char *commonString(char *p1, char *p2)
{
char r[MAX_LENGTH] = { };
for (int i = 0; i < strlen(p1); i++)
for (int j = 0; j < strlen(p2); j++)
if (p1[i] == p2[j])
strcat(r, &p1[i]);
static char res[MAX_LENGTH] = { };
removeDup(res, r);
return res;
}
int main()
{
printf("%s\n", commonString("padinton", "paqefwtdjetyiytjneytjoeyjnejeyj"));
return 0;
}
$ cc string.c -o string && ./string
padinto

mysql_init overwriting memory space

When I call mysql_init(mysql);, it is overwriting a char array. I do not understand what I am doing wrong. My code:
void prepare_mysql(MYSQL *mysql) {
mysql_library_init(0, NULL, NULL);
mysql_init(mysql);
}
void get_uid(char *src, char *dst) {
int i, len, count = 0;
len = strlen(src);
for(i = 0; i != len; i++) {
if(src[i] == '-') { // iterate until a - sign is found
break;
}
dst[count] = src[i]; // save char into dst
count++;
}
dst[count] = '\0'; // add null char at the end of char array, otherwise everything will explode...
// dst is now: 389302
}
int main(int argc, char *argv[]) {
// argv[1] is for example: 389302-8232
char uid;
get_uid(argv[1], &uid);
printf("uid = %s\n", &uid); // prints: 389302 (correct)
MYSQL conn;
prepare_mysql(&conn);
printf("uid = %s\n", &uid); // prints: 3 (the first char only.. why?)
mysql_close(&conn);
mysql_library_end();
return 0;
}
If I call the get_uid function after I call mysql_init, I cannot call mysql_close(&conn) because I get a Segmentation fault. Please help, I cannot understand..
Edit:
I have added this in main:
char *uid = malloc(strlen(argv[1]));
And later in main, I call free(uid);. Now it seems to be printing correctly everywhere before I call free.
You don't have a char array - uid is only a char.

imitate strcpy function in c using char pointers

I am try to write a user defined function which will do exactly what strcpy() library function do. But although there is no error, my program crashes and not copying second string to first string. What's wrong with this code and how to fix it?
#include<stdio.h>
#include<string.h>
int main(){
char *ch1="abcd";
char *ch2="efgh";
str_cpy(ch1,ch2);
}
str_cpy(char *c1,char *c2){
int i=0;
while(c1[i]!='\0'){
i++;
}
printf("%c",*(c1+3));
int k;
for(k=0;k<=i;k++){
*(c1+k)=*(c2+k);
}
}
String literals are generally put into read only area, that's why the program crashed when you are writing into c1. The destination string needs to be an array or allocated buffer:
char c1[5];
str_cpy(c1, c2);
Also, in the function, it looks you are copying c2 to c1, but you are counting the length of c1, you should count the length of c2 instead:
// copy string c2 to c1
void str_cpy(char *c1, const char *c2){
int i=0;
while(c2[i]!='\0'){
i++;
}
int k;
for(k=0;k<=i;k++){
*(c1+k)=*(c2+k);
}
}
Your program invokes undefined behavior because you are trying to write to a string literal. String literals can be stored in read only memory, which is probably the case on your system, hence causing a crash.
Note that your string copying function can perform the copy in a single loop:
char *str_cpy(char *c1, const char *c2) {
for (int i = 0;; i++) {
c1[i] = c2[i];
if (c1[i] == '\0')
return c1;
}
}
You can verify the behavior with a modified main:
#include <stdio.h>
char *str_cpy(char *c1, const char *c2) {
for (int i = 0;; i++) {
c1[i] = c2[i];
if (c1[i] == '\0')
return c1;
}
}
int main(void) {
char buf[20];
char *ch2 = "Hello world\n";
printf("%s\n", str_cpy(buf, ch2));
return 0;
}
Here is a possible rework of your code, which doesn't have to pre-define buffer size (c1). You simply pass the buffer address. Also, please note that such buffer has to be freed once used (for example, if declared in local scope, not in main()):
#include <stdio.h>
#include <stdlib.h>
char *str_cpy(char **c1, const char *c2) {
int i, size = 0;
for(i = 0; ; i++)
if(c2[i] == '\0')break;
size = i + 1;
if(!(*c1 = realloc(*c1,size*sizeof(char))))
return *c1;//or devise some more sophisticated error handling
for (i = 0;; i++) {
(*c1)[i] = c2[i];
if (c2[i] == '\0')
return *c1;
}
}
int main(void){
char *ch1 = malloc(1); //you're responsible for freeing it, once used
char *ch2 = "Hello, everybody in the neighborhood!";
printf("%s\n",str_cpy(&ch1,ch2));
free(ch1);
return 0;
}
Please, also note you don't need to #include <string.h>

C: Take parts from a string without a delimiter (using strstr)

I have a string, for example: "Error_*_code_break_*_505_*_7.8"
I need to split the string with a loop by the delimiter "_*_" using the strstr function and input all parts into a new array, let's call it -
char *elements[4] = {"Error", "code_break", "505", "7.8"}
but strstr only gives me a pointer to a char, any help?
Note: the second string "code_break" should still contain "_", or in any other case.
This will get you half-way there. This program prints the split pieces of the string to the standard output; it does not make an array, but maybe you can add that yourself.
#include <stdio.h>
#include <string.h>
#include <malloc.h>
void split(const char * str, const char * delimiter)
{
char * writable_str = strdup(str);
if (writable_str == NULL) { return; }
char * remaining = writable_str;
while (1)
{
char * ending = strstr(remaining, delimiter);
if (ending != NULL) { *ending = 0; }
printf("%s\n", remaining);
if (ending == NULL) { break; }
remaining = ending + strlen(delimiter);
}
free(writable_str);
}
int main(void) {
const char * str = "Error_*_code_break_*_505_*_7.8";
const char * delimiter = "_*_";
split(str, delimiter);
return 0;
}
Here is a function that splits a string into an array. You have to pass the size of the array so that the function won't overfill it. It returns the number of things it put into the array. What it puts into the array is a pointer into the string that was passed. It modifies the string by inserting null characters to end the pieces - just like strtok does.
#include<string.h>
#include<stdio.h>
int split(char *string, char *delimiter, char* array[], int size)
{
int count=0;
char *current=string;
char *next;
while(current && *current!='\0')
{
next=strstr(current,delimiter);
if(!next)break;
*next='\0';
if(count<size) array[count++]=current;
current=next+strlen(delimiter);
}
if(count<size) array[count++]=current;
return count;
}
int main()
{
char string[100]="Error_*_code_break_*_505_*_7.8";
char *array[10];
int size=split(string,"_*_",array,10);
for(int i=0;i<size;i++) puts(array[i]);
return size;
}

Passing multiple strings into a function

i am trying to read several strings into a function for processing. The instructions are to pass each string into the function (not create a 2d array of strings). The parameters must stay the same. Here is what i tried
#include <stdio.h>
#include <math.h>
void convert(char s[]), int counts[]);
int main(void)
{
int i = 0;
int d[2] = {};
char text0[] = "this IS a String 4 you.";
char text1[] = "This sample has less than 987654321 leTTers.";
while(i<2)
{
convert (text[i],d); """ this is wrong but i dont know how to correctly do this
i = i +1;
}
}
void convert(char s[]), int counts[])
{
printf("%s this should print text1 and text2", s );
}
So i have a couple of questions. Is there some sort of special character/operator similiar to the glob module in python that can correctly do the convert (text[i],d) part for me where i try to read in each string. Also the int counts[] purpose is to be filled in with the word and character count in the function. So if i fill in this array in function convertwill main also recognize it since i need to print the word/character count in main without returning the actual counts in convert
You could use temporary string pointer array to pass all strings:
char text1[] = "This sample has less than 987654321 leTTers.";
char const * texts[] = { text0, text1 };
convert (texts, 2, d);
}
void convert(char const * s[], size_t n, int counts[])
{
while(n--) {
*counts++ = strlen(*s);
printf("%s\n", *s++);
}
}
Some notes:
I added char const to function argument type. You should always do that when function does not change the string. If you need to change the string in function, just remove the const.
There is extra argument size_t n to pass array array element count to function. size_t can be found in stddef.h.
i think u lost a "(" in "void convert(char s[]), int counts[]);".
it should be void convert((char s[]), int counts[]);
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void convert(char s[], int counts[]);
int main(void){
int i = 0;
int d[2] = {0};
char text0[] = "this IS a String 4 you.";
char text1[] = "This sample has less than 987654321 leTTers.";
char *text[] = { text0, text1 };
for(i=0; i<2; ++i){
convert (text[i], d);
printf("%d, %d\n", d[0], d[1]);
}
}
void convert(char s[], int counts[]){
printf("%s\n", s );
{
char *temp = strdup(s);
char *word, *delimiter = " \t\n";//Word that are separated by space character.
int count_w=0, max_len=0;
for(word = strtok(temp, delimiter); word ; word = strtok(NULL, delimiter)){
int len = strlen(word);
if(max_len < len)
max_len = len;
++count_w;
}
counts[0] = count_w;
counts[1] = max_len;
free(temp);
}
}

Resources