I have to write a function which takes in 2 double pointers (both to char type). The first double pointer has a string of query values and the 2nd one has stopwords. The idea is to eliminate the stopwords from the query string and return all the words without those stopwords.
For example
Input - query: “the”, “new”, “store”, “in”, “SF”
stopwords: “the”, “in”
OUTPUT
new
store
SF
I have written the following code while trying to use strtok which takes in only single pointers to char types. How do I access the contents of a double pointer?
Thanks
#include <stdio.h>
void remove_stopwords(char **query, int query_length, char **stopwords, int stopwords_length) {
char *final_str;
final_str = strtok(query[0], stopwords[0]);
while(final_str != NULL)
{
printf("%s\n", final_str);
final_str = strtok(NULL, stopwords);
}
}
For simplicity's sake, you can assume a double pointer to be equivalent to a 2d array (it is not!). However, this means that you can use array-convention to access contents of a double pointer.
#include <stdio.h>
#include <string.h>
char *query[5] = {"the","new","store","in","SF"};
char *stopwords[2] = {"the","in"};
char main_array[256];
void remove_stopwords(char **query,int query_length, char **stopwords, int stopwords_length);
int main()
{
remove_stopwords(query,5,stopwords,2);
puts(main_array);
return 0;
}
void remove_stopwords(char **query,int query_length, char **stopwords, int stopwords_length)
{
int i,j,found;
for(i=0;i<query_length;i++)
{
found=0;
for(j=0;j<stopwords_length;j++)
{
if(strcmp(query[i],stopwords[j])==0)
{
found=1;
break;
}
}
if(found==0)
{
printf("%s ",query[i]);
strncat(main_array,query[i],strlen(query[i]));
}
}
}
Output: new store SF newstoreSF
#Binayaka Chakraborty's solution solved the problem but I thought it might be useful to provide an alternative that used pointers only and showed appropriate use of strtok(), the use of which may have been misunderstood in the question.
In particular, the second parameter of strtok() is a pointer to a string that lists all the single-character delimiters to be used. One cannot use strtok() to split a string based on multi-character delimiters, as appears to have been the intention in the question.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void remove_stopwords(char *query, char **stopwords) {
char *final_str = strtok(query, " ");
while(final_str != NULL) {
int isStop = 0;
char **s;
for (s = stopwords; *s; s++) {
if (strcmp(final_str,*s) == 0) {
isStop = 1;
}
}
if (!isStop) printf("%s ", final_str);
final_str = strtok(NULL, " ");
}
}
int main() {
const char *q = "the new store in SF";
char *query = malloc(strlen(q)+1);
/* We copy the string before calling remove_stopwords() because
strtok must be able to modify the string given as its first
parameter */
strcpy(query,q);
char *stopwords[] = {"the", "in", NULL};
remove_stopwords(query,stopwords);
return 0;
}
The approach shown here also avoids the need to hard code the sizes of the arrays involved, which therefore reduces potential for bugs.
Related
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;
}
As you can see I have this code it takes a command (char array ) and divides it into two diffrent arrays if there is "|" between them.What I want is not to print it with the function but return these two new arrays to main and then print them ?
How can I do it ?
#include <fcntl.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <unistd.h>
int main()
{
int a;
int status,n,i;
char command[4000];
write(STDOUT_FILENO,"Shell>",6);
n=read(STDIN_FILENO,command,4000);
void getArguments(char **,char*);
char *getStdOutFileName(char *);
if(n>0)
{
for(i=0;i<n;i++)
{
bugrafonk(command,&i);
printf("%s",First);
printf("%s",Second);
}
}
}
void bugrafonk(char* c,int*length)
{
int i;
int a;
char First[4000];
char Second[4000];
for(i=0;i<length;i++)
{
if(c[i]=='|')
{
i=a;
for(i=0;i<a;i++)
{
char First[i];
}
printf("---");
for(i=a;a<length;i++)
{
char Second[i];
}
}
}
return(First,Second); //is this true ?
}
There are some unnecssery declaration in the main now just avoid them I will use them later on.
To retun char * to main you need to send pointers to your function which are attached to memory that you can use
For example,
....
char return1[50]
char return2[50]
....
split_function(command, return1, return2);
....
The answer depends on where you store the results of your calculations.
In your current implementation both First and Second arrays are allocated inside the bugrafonk function and thus will be destroyed when the function is finished.
One possible option would be to allocate memory for result arrays outside the function and pass pointers to the function.
char first[4000], second[4000];
bugrafonk(..., first, second);
// use first and second
And bugrafonk implementation:
void bugrafonk(your arguments..., char *first, char *second)
{
...
}
Also, I have no idea what the mysterious word bugrafonk means ;)
The function implemented here splits the string by terminating the first part, and returns a pointer to the second part.
You don't need to return 2 pieces of information since you already know where the first string is. Note that this will not work if a string literal is passed since you cannot modify it, but that's not the case here.
#include <stdio.h>
#include <string.h>
char* bugrafonk(char* c); // function prototype
int main(void)
{
char command[4000];
char *split;
scanf("%3999s", command); // enter limited length string
split = bugrafonk(command); // this splits the string
printf("First part: %s\n", command); // print first half
if (split != NULL) // if there is a second half
printf("Second part: %s\n", split); // print second half
}
char* bugrafonk(char* c) // returns string pointer
{
char *cptr = strchr(c, '|'); // find that char
if (cptr != NULL) // if it was found
{
*cptr = '\0'; // terminate first part here
cptr++; // advance pointer to next part
}
return cptr;
}
Program output:
one|two
First part: one
Second part: two
You may choose to return a pointer to char, and then pass two arrays that will be modified in the body of the function.:
char *func(char arr[], char* arr2 /* other parameters */)
{ /* process arr and arr2 */
// return new array one. arr2 doesn't need to be returned.
return arr;
}
// in main:
char command[4000];
char arr2[4000]; // First
char *arr3 = func(command, arr2); // Second
Or just pass all arrays as arguments to the function and then return void, since they will be modified in the function.
I'm new in c programming and I want to pass array from library.
I have function in library c file that creates char array. How to use this array in main function. This is short code of something I tried:
libfile.c
char *myArray;
void PopulateArray()
{
// Getting data from serial port in char buffer[100]
myArray = buffer;
}
libfile.h
exter char *myArray;
void PopulateArray();
program.c
int main()
{
// in fore loop
printf("%s\n" , myArray[i]);
}
This is just one of combinations that I have tried but nothing works.
How to do this?
To pass an array from a library function to the surrounding code, you can use the return value of a function or use a pointer-to-pointer argument.
See the following example code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* createSourceCopy() {
const char *source = "Example Text";
// We got some text in variable source;
const size_t sourceSize = strlen(source);
char *result = (char*)malloc(sizeof(char)*(sourceSize+1));
strncpy(result, source, sourceSize);
return result;
}
A user of your library could use the function like this:
main() {
char *result = createSourceCopy();
// Do something with result.
// After the use, destroy the array
delete[] result;
return 0;
}
Another way how to pass an array is this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
bool copySourceText( char **outText ) {
const char *source = "Example Text";
// We get some text in variable source;
const size_t sourceSize = strlen(source);
*outText = new char[sourceSize];
strncpy(*outText, source, sourceSize);
return true; // success
}
This second variant has the benefit that the return value can be used as status. The function could return true on success, or false if there was an error.
This second version can be used like this.
int main() {
char *result;
if (copySourceText(&result)) {
// Do something with result.
// After the use, destroy the array
free(result);
result = NULL;
} else {
// Error handling
}
return 0;
}
It's not clear exactly what's going wrong in the code you posted (it would help to see more code), but assuming your problem isn't a compilation error, one of these lines might be wrong:
char *myArray;
printf("%s\n" , myArray[i]);
char *myArray declares a pointer to char (which would be appropriate for a single string).
The printf line dereferences myArray (producing a char, i.e. one character). You're passing down a char, but the %s format expects a pointer-to-char.
If you want to print the string character-by-character, you could use %c:
for (i = 0; i < length; i++) {
printf("%c\n", myArray[i]); /* or %x or %d if you want */
}
Otherwise, if myArray is one string and is null-terminated (see Why is a null terminator necessary?), then you could do:
printf("%s\n" , myArray); /* [i] removed, no for loop necessary */
For example:
This is what I tried:
#include "stdafx.h"
#include <ctype.h>
char *mystrcat(char *s1p, char *s2p);
char main(void)
{
...........................
}
char *mystrcat(char *s1p, char *s2p)
{
printf("whatever = %s%s\n", s1p, s2p);
return 0;
}
How do I make this work with the 3rd pointer and have it store p1 and p2?
Replace: *mystrcat(string1, string2);
With: char *string3 = mystrcat(string1, string2);
Also if your teacher wants char*'s instead of
char string1[80];
char string2[80];
You could do
char *string1 = malloc(80*sizeof(char));
char *string2 = malloc(80*sizeof(char));
To concat your strings:
char *mystrcat(char *s1p,char *s2p) {
char *cat = malloc(2*80*sizeof(char));
int i = 0;
while(s1p[i]!='\o') {
cat[i] = s1p[i];
i++;
}
int j = 0;
while(s2p[j]!='\o') {
cat[i+j] = s2p[j];
j++;
}
return cat;
}
Bad coding habits aside (I've been doing C for a while, still haven't fixed some of em), there is one error I see: mystrcat(string1, string2). The return type is char, but the function itself has the pointer "in it" (hard to explain). So it should just be mystrcat(string1, string2)
It sounds like you want to write a function to concatenate strings. To do this you need to be able to visualize the strings in your head, the 2 input strings and the resultant string.
Here's an algorithm that should solve it:
Create a result string that has enough space for the total number of characters in the given input plus 1 for the terminating nul char.
Copy the bytes from the first string to the result.
Append the characters from the esconds string to the result
Append a nul character
return the result
Programming is the ability to see a problem, devise an algorithm and then implement in a programming language.
#include "stdafx.h"
#include <stdlib.h>
#include <string.h>
#include <Windows.h>
#include <ctype.h>
char *mystrcat(char*s1p, char*s2p); // Prototype
int main(void)
{
char *string1 = malloc(80*sizeof(char));
char *string2 = malloc(80*sizeof(char));
printf("Enter in string 1");
scanf("%s", string1);
printf("Enter in string 2");
scanf("%s", string2);
char *mystrcat((string1,string2));
return 0;
}
char *mystrcat(char *s1p,char *s2p)
{
char *cat = malloc(2*80*sizeof(char));
int i = 0;
while(s1p[i]!='\o') {
cat[i] = s1p[i];
i++;
}
int j = 0;
while(s2p[j]!='\o') {
cat[i+j] = s2p[j];
j++;
}
return cat;
}
this is the code i got so far with all of your lots help, i included everthing top to bottom, i am using MSVS 2012 and the reason i am posting this because i have an error on 'malloc' the error as fellows
3 IntelliSense: a value of type "void *" cannot be used to initialize an entity of type "char *" c:\Users\Sid\Documents\Visual Studio 2012\Projects\PORTFOLIO QUESTION 3\PORTFOLIO QUESTION 3\PORTFOLIO QUESTION 3.cpp 32
I'm trying to parse a URL query string in C and I don't see how to do it elegantly. Any hints or suggestions would be greatly appreciated:
static void readParams(char * string, char * param, char * value) {
char arg[100] = {0}; // Not elegant, brittle
char value2[1024] = {0};
sscanf(string, "%[^=]=%s", arg, value2);
strcpy(param, arg);
strcpy(value, value2);
}
char * contents = "username=ted&age=25";
char * splitted = strtok (contents,"&");
char * username;
char * age;
while (splitted != NULL)
{
char param[100]; // Not elegant, brittle
char value[100];
char * t_str = strdup(splitted);
readParams(t_str, param, value);
if (strcmp(param, "username") == 0) {
username = strdup(value);
}
if (strcmp(param, "age") == 0) {
age = strdup(value); // This is a string, can do atoi
}
splitted = strtok (NULL, "&");
}
The problem I kept on having is that because of the strtok function anything that was seemed more intelligent to do before the last strtok function seemed to break the while loop.
You either need to tailor complex and effective parser or settle with libraries that will do it for you.
uriparser should provide all you need (plus it supports unicode).
In general strtok breaks the source string for use by some other functions. Here is a bare bones example of using strtok to tokenize a string
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define MX_SPLIT 128
char **split( char **result, char *working, const char *src, const char *delim)
{
int i;
strcpy(working, src); // working will get chppped up instead of src
char *p=strtok(working, delim);
for(i=0; p!=NULL && i < (MX_SPLIT -1); i++, p=strtok(NULL, delim) )
{
result[i]=p;
result[i+1]=NULL; // mark the end of result array
}
return result;
}
void foo(const char *somestring)
{
int i=0;
char *result[MX_SPLIT]={NULL};
char working[256]={0x0}; // assume somestring is never bigger than 256 - a weak assumption
char mydelim[]="!##$%^&*()_-";
split(result, working, somestring, mydelim);
while(result[i]!=NULL)
printf("token # %d=%s\n", i, result[i]);
}
I do:
char querystring[]="a=1&b&c=3&d=&meh=5";
int pc=0;
char *tok;
char *otok;
for(tok=strtok(querystring,"&");tok!=NULL;tok=strtok(tok,"&")) {
pc++;
otok=tok+strlen(tok)+1;
tok=strtok(tok,"=");
fprintf(stderr,"param%d: %s ",pc,tok);
tok=strtok(NULL,"=");
fprintf(stderr,"value%d: %s\n",pc,tok);
tok=otok;
};
remember that strtok destroys the original so before this just make a copy of the querystring.
Assumptions is not a bad thing, in general, and especially in fast, robust and protective code (consider, for example, that your input string have invalid format).
To reach most elastic code however, you need to manually allocate (and deallocate after usage!) memory for strings, the size of which should be to total lenght of an input string (one more time where reasonable limit is a must), since it's unknown (in general) how long is param and value string parts.