Passing multiple strings into a function - c

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);
}
}

Related

How to add/delete element in Flat array in C

I have a structure inside which char array and int value is maintained. I want to treat this char array as a flat array to store the list of strings and the offset will track the starting position where the string is added in the array.
Structure is shown below:
struct A
{
char element[256];
int offset;
}
Also, I want to delete the strings after performing some operation if found.
Please let me know if this feasible. If yes then how?
Yes, append to a.element[a.offset].
To delete, set a.element[0] to the null byte. C strings end at a null byte.
#include <stdio.h>
#include <string.h>
typedef struct
{
char element[256];
int offset;
} A;
void A_append(A* a, const char *str) {
// Concatenate on the end of element.
strcat(&a->element[a->offset], str);
// Increment the offset to the new end.
a->offset += strlen(str);
}
void A_delete(A* a) {
a->element[0] = '\0';
a->offset = 0;
}
int main() {
A a = { .element = "" };
a.offset = 0;
char string1[] = "one";
A_append(&a, string1);
char string2[] = "two";
A_append(&a, string2);
puts(a.element);
A_delete(&a);
puts(a.element);
}
You can also store a pointer to the end of element. It's the same thing, just more direct.
#include <stdio.h>
#include <string.h>
typedef struct
{
char element[256];
char *end;
} A;
void A_append(A* a, const char *str) {
// Concatenate nto the end of element.
strcat(a->end, str);
// Increment the pointer to the new end.
a->end += strlen(str);
}
void A_delete(A* a) {
a->element[0] = '\0';
a->end = a->element;
}
int main() {
A a = { .element = "" };
a.end = a.element;
char string1[] = "one";
A_append(&a, string1);
char string2[] = "two";
A_append(&a, string2);
puts(a.element);
A_delete(&a);
puts(a.element);
}
Finally, if you want to store a list of strings, not concatenate them, consider storing them as pointers.
Since all we have to go on is the question if it's feasible - and the answer is yes. Here's a way showing that it is:
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct A A;
struct A {
char element[256];
int offset;
};
A *A_create() {
A *a = malloc(sizeof *a);
a->offset = 0;
return a;
}
void A_destroy(A *a) {
free(a);
}
// return false if the string doesn't fit
// true if it's successfully added
bool A_add_string(A *a, const char *str) {
size_t len = strlen(str);
if(a->offset + len >= sizeof a->element) return false;
memcpy(a->element + a->offset, str, len + 1);
a->offset += len + 1;
return true;
}
You can now create an A, add \0 terminated strings to it and finally destroy it:
A *a = A_create();
A_add_string(a, "Hello");
A_add_string(a, "world");
A_destroy(a);

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;
}

Returning string from function having multiple NULL '\0' in C

I am compressing string. And the compressed string sometimes having NULL character inside before the end NULL. I want to return the string till the end null.But the compressor function is returning the sting till the occurring of the first NULL. Please help me.
char* compressor(char* str)
{
char *compressed_string;
//After some calculation
compressed_string="bk`NULL`dk";// at the last here is automatic an NULL we all know
return compressed_string;
}
void main()
{
char* str;
str=compressor("Muhammad Ashikuzzaman");
printf("Compressed Value = %s",str);
}
The output is : Compressed Value = bk;
And all other characters from compressor function is not here. Is there any way to show all the string.
The function returns "entire string". It is printf that outputs it until the null character will be encountered.
You could define the function the following way
char * compressor( const char* source, size_t *result_len );
To understand the problem consider the following code
#include <stdio.h>
char * compressor( const char* source, size_t *result_len )
{
char *compressed_string = "bk\0dk";
*result_len = sizeof( "bk\0dk" );
return compressed_string;
}
int main( void )
{
char* str;
size_t n;
str = compressor( "Muhammad Ashikuzzaman", &n );
int i;
printf( "Compressed Value = " );
for ( char *p = str; n; n -= i + 1, p += i + 1 )
{
i = printf( "%s", p );
}
return 0;
}
The output is
Compressed Value = bkdk
#include <stdio.h>
#include <stdlib.h>
char* func(char *str, int *length)
{
int i;
*length=9;//Put string length you calculated
str=(char*)malloc(*length*sizeof(char));
for(i=0;i<5;i++)
str[i]=i+65;
str[5]=0;
str[6]=65;
str[7]=67;
str[8]=0;
return str;
}
int main()
{
char *str;
int i,length=0;
str=func("Muhammad Ashikuzzaman",&length);
for(i=0;i<length;i++)
printf("%c",str[i]);
scanf("%d",&i);
return 0;
}
Solution using std::string:
#include <string>
#include <iostream>
#include <iterator>
std::string compressor(char* str)
{
char *compressed_string;
int len; // this is the size of the compressed data
//...
// compress the data and assume that len has the number of characters
//...
std::string theString(compressed_string, len);
// clean up any memory here.
//...
return theString;
}
using namespace std;
int main()
{
std::string str = compressor("Muhammad Ashikuzzaman");
std::copy(str.begin(), str.end(), std::ostream_iterator<char>(cout,""));
}
Note the usage of std::string, as well as how the information is outputted using the copy algorithm function. The reason why copy is used instead of printf is to ensure that all of the characters, including the (invisible) embedded NULL's are printed.
Also, the size of the compressed data is easily retrieved by calling str::size().

How to use qsort for an array of strings?

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int sortstring(const void *str1, const void *str2) {
const char *rec1 = str1;
const char *rec2 = str2;
}
void sortutil(char* lines[]) {
qsort(lines, 200, sizeof(char), sortstring);
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sortutil.h"
int getarray(char *lines[]) {
int i = 0;
char *text = (char *)malloc(200);
while (fgets(text, 200, stdin) != NULL) {
lines[i] = text;
i++;
text = (char *)malloc(200);
}
return i;
}
void printarray(char *lines[], int max) {
for (int i = 0; i < max; i++)
printf("%s\n\n", lines[i]);
}
int main(int argc, char* argv[]) {
char* arr[100];
int numlines = getarray(arr);
printf("There are %d lines\n", numlines);
printarray(arr, numlines);
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-s") == 0) {
sortutil(arr);
printarray(arr, numlines);
}
}
}
When I send in a file with arbitrary text, It'll read the file and print it out, but when i call -s and call the qsort function, it comes back with nulls. I'm sure I am using qsort incorrectly, what is the right way to use it for an array to char pointers?
Your comparator is being sent each pair by-address. I.e. they're pointer-to-pointer-to-char.
Change the comparator to:
int sortstring( const void *str1, const void *str2 )
{
char *const *pp1 = str1;
char *const *pp2 = str2;
return strcmp(*pp1, *pp2);
}
Likewise, your sortutil needs to know the number of items being sorted, as well as pass the correct size of each item. Change that to:
void sortutil(char* lines[], int count)
{
qsort(lines, count, sizeof(*lines), sortstring);
}
Finally, the call from main() should look like this:
sortutil(arr, numlines);
That should do it.
What the compar function gets are pointers to the elements in your array, which in this case, are pointers to char. So the parameters str1 and str2 are actually pointers to pointers to char. You must cast them like this:
int sortstring( const void *str1, const void *str2 )
{
const char *rec1 = *(char**)str1;
const char *rec2 = *(char**)str2;
int val = strcmp(rec1, rec2);
return val;
}
Then you have to use the proper element size in qsort.
qsort(lines, 200, sizeof(char*), sortstring);
This line is incorrect.
qsort(lines, 200, sizeof(char), sortstring);
Change it to
qsort(lines, 200, sizeof(char*), sortstring);

Null terminating char pointer

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
}
}
}

Resources