I wrote the below code which replaces '|' characters from the string.
#include <stdio.h>
#include <stdlib.h>
void remove_pipes(char*);
main (int argc, char **argv)
{
char string1[] = "|||||||||||||";
remove_pipes(string1);
printf("String1 = %s", string1);
char string2[] = "h|e|l|l|o";
remove_pipes(string2);
printf("String2 = %s", string2);
}
void remove_pipes(char* input)
{
for(; *input; input++)
{
if(*input == '|')
{
*input = ' ';
}
}
}
Now I need to modify this method to remove the '|' character from the string. I am not sure how to do that. Hope someone can give me some hint.
Use a char pointer to travel the input and modify it:
#include <stdio.h>
#include <stdlib.h>
void remove_pipes(char*);
main (int argc, char **argv)
{
char string1[] = "|||||||||||||";
printf("String1 = %s\n", string1);
remove_pipes(string1);
printf("String1 = %s\n", string1);
char string2[] = "h|e|l|l|o";
printf("String2 = %s\n", string2);
remove_pipes(string2);
printf("String2 = %s\n", string2);
}
void remove_pipes(char* input)
{
unsigned idx = 0;
char* aux = input;
for(; *input; input++)
{
if (*input != '|')
{
*(aux + idx++) = *input;
}
}
*(aux + idx) = '\0';
}
Related
This program is intended to return a string, when passing command line arguments it works as intended, however when arguments are inserted manually it returns a number instead of a string and I can't identify why this is happening. It seems I did something wrong while printing the string with "printf ("The modified expression is: %s", s2);", since it never prints the intended string.
#include <stdio.h>
#include <math.h>
#include <string.h>
int nv(char *s1, char c1)
{
int i,count=0;
i=0;
if (s1 != NULL)
{
while(s1[i]!=0)
{
if (s1[i]==c1)
++count;
++i;
}
}
return count;
}
int po(char *s1, char c1)
{
int i;
i=0;
if (s1 != NULL)
{
while(s1[i]!=0)
{
if (s1[i]==c1)
return i;
++i;
}
}
return -1;
}
char *s(char *s1, char c1, char c2)
{
int i;
char expression[256];
char rep1[256];
char rep2[256];
if (s1 == NULL)
{
printf("No command line arguments! Please insert the expression to modify.\n");
scanf(" %s",expression);
s1=expression;
printf("Insert the character to replace.\n");
scanf(" %s",rep1);
c1=*rep1;
printf("Insert the replacement character.\n");
scanf(" %s",rep2);
c2=*rep2;
}
i=0;
if (s1 != NULL)
{
while(s1[i]!=0)
{
if (s1[i]==c1)
s1[i]=c2;
++i;
}
}
return s1;
}
int main(int argc, char *argv[])
{
int x,y,i = 0;
char *s1 = NULL,c1 = '\0',c2 = '\0';
char *s2 = NULL;
if(argc!=1)
{
x = nv(argv[1], argv[2][0]);
y = po(argv[1], argv[2][0]);
s1 = s(argv[1], argv[2][0], argv[3][0]);
printf("i=%d, count=%d, po=%d\n\n",i,x,y);
printf("\n %s \n\n", s1);
printf("\n\n");
}
else
{
x = nv(argv[1], argv[2][0]);
y = po(argv[1], argv[2][0]);
s2 = s(s1,c1,c2);
printf ("The modified expression is: %s", s2);
printf("\n\n");
}
return 0;
}
#include <stdio.h>
#include <string.h>
void separate(char s[20], char dummy[10], char* p){
strcpy(dummy, s);
for (int i = 0; i < strlen(dummy); i++){
if (dummy[i] == ' '){
dummy[i] = '\0';
}
}
*p = strchr(s, ' ');
p++;
}
int main(){
char s[10];
char dummy[10];
char l;
gets(s);
separate(s, dummy, &l);
puts(dummy);
puts(l);
}
I'm having trouble passing the last name to the main function as a string, the goal is to separate a string that consists of someone's first and last name.
#include <stdio.h>
#include <string.h>
void separate(char name[], char first[], char last[]){
strcpy(first, name);
for (int i = 0; i < strlen(first); i++){
if (first[i] == ' '){
first[i] = '\0';
}
}
char *p = strchr(name, ' ');
p++;
strcpy(last, p);
}
int main(){
char n[10], f[10], l[10];
gets(n);
separate(n, f, l);
puts(f);
puts(l);
}
I figured it out, thanks for the help anyway.
Here is an example of using fgets:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFSIZE 20
#define NAMESTRLEN 10
void separate(char buffer[], char firstname[], char lastname[]);
int
main(void) {
char buffer[BUFFSIZE], firstname[NAMESTRLEN], lastname[NAMESTRLEN];
size_t slen;
printf("Enter first and last name: ");
if (fgets(buffer, BUFFSIZE, stdin) == NULL) {
printf("Error reading into buffer.\n");
exit(EXIT_FAILURE);
}
slen = strlen(buffer);
if (slen > 0) {
if (buffer[slen-1] == '\n') {
buffer[slen-1] = '\0';
} else {
printf("Exceeded buffer length: %d.\n", BUFFSIZE);
exit(EXIT_FAILURE);
}
}
if (!*buffer) {
printf("Nothing entered.\n");
exit(EXIT_FAILURE);
}
separate(buffer, firstname, lastname);
printf("Firstname = %s\n", firstname);
printf("Lastname = %s\n", lastname);
return 0;
}
void
separate(char buffer[], char firstname[], char lastname[]) {
int i;
char *last;
const char sep = ' ';
for (i = 0; buffer[i] != sep; i++) {
firstname[i] = buffer[i];
}
firstname[i] = '\0';
last = strchr(buffer, sep);
last++;
strcpy(lastname, last);
}
I'm trying to obtain a file from its path.
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char split_path(char *path){
char *str1, *delim;
char buf[255];
int i, max;
char *token = "/";
for (i = 1, str1 = path; ; i++, str1 = NULL){
delim = strtok(str1, token);
if (delim == NULL){
break;
}
buf[i] = *delim;
max = i;
}
char last = buf[max];
return last;
}
int main(int argc, char *argv[]){
if (argc != 3){
fprintf(stderr, "Usage: %s string delim\n", argv[0]);
exit(EXIT_FAILURE);
}
char last = split_path(argv[1]);
printf("%c\n", last);
return 0;
}
So if I enter an input of /a/b/c/d , it returns 'd' which is what I want.
But if I enter an input of /a/b/c/d.txt, it only returns 'd' without the '.txt', when what I need is 'd.txt'.
It seems to be only getting the first index after the last / . I can't seem to figure out the problem.
Help much appreciated.
Your problem is split_path is returning the first letter of the last good result of strtok.
Change split_path to return a string, and modify it slightly... something like this:
char *split_path(char *path){
char *str1, *delim;
int i, max;
char *last = NULL;
char *token = "/";
for (i = 1, str1 = path; ; i++, str1 = NULL){
delim = strtok(str1, token);
if (delim == NULL){
break;
}
last = delim;
}
return last;
}
int main(int argc, char *argv[]){
if (argc != 3){
fprintf(stderr, "Usage: %s string delim\n", argv[0]);
exit(EXIT_FAILURE);
}
char *last = split_path(argv[1]);
printf("%s\n", last);
return 0;
}
I'll show you how to do it two ways. The easiest is to include libgen.h and use basename(), if this exists on your system. It does what you wanted. But if you want to write your own function, you can do it with strrchr(), which finds the last occurrence of a character in a string.
#include <stdio.h>
#include <string.h> // for strrchr()
#include <libgen.h> // for basename()
const char *my_basename(const char *path)
{
const char *lastSlash = strrchr(path, '/');
if (lastSlash)
return lastSlash+1;
return path;
}
int main(int argc, char *argv[])
{
if (argc < 2)
return;
printf("Full path = %s\n", argv[1]);
printf("basename() = %s\n", basename(argv[1]));
printf("my_basename() = %s\n", my_basename(argv[1]));
return 0;
}
Sample output:
Full path = /aaa/bbb/ccc/ddd.txt
Filename = ddd.txt
Filename = ddd.txt
Also after I want to add a key to each letter like 'a' + 1 = 'b'. So I want to take a string for instance "Hello" then do
char 1 = H + 1;
char 2 = E + 1;
etc.
printf("%c" + "%c" + "%c" + "%c" + "%c", 1 , 2 , 3 , 4 , 5);
also I would love for this to be automated because IDK how long the string might be and what key theyre are going to use.
You can do something like this:
#include<stdio.h>
#include<string.h>
int main()
{
char text[] = "Hello";
int i=0;
int size= strlen(text);
for(i=0;i<size;i++)
{
//something here
}
return 0;
}
Assuming the string is mutable, you can update it in place:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void update(char *s, int delta)
{
while(*s)
*s++ += delta;
}
int main(int argc, char **argv)
{
char str[] = "Hello";
update(str, 1);
printf("Encoded: \"%s\"\n", str);
update(str, -1);
printf("Decoded: \"%s\"\n", str);
return 0;
}
If the string is immutable, you will need to make a copy of it, and update the copy.
int main(int argc, char **argv)
{
const char str[] = "Hello";
char *copy = strdup(str);
update(copy, 1);
printf("Encoded: \"%s\"\n", copy);
update(copy, -1);
printf("Decoded: \"%s\"\n", copy);
free(copy);
return 0;
}
You should read about dynamic arrays in C.
#include <stdio.h>
#include <string.h>
char* code(const char* message)
{
int i = 0;
char* coded;
for (i = 0; i < strlen(message); i++)
{
coded[i] = message[i] - 3;
}
return coded;
}
char* decode(const char* message)
{
int i = 0;
char* coded;
for (i = 0; i < strlen(message); i++)
{
coded[i] = message[i] + 3;
}
return coded;
}
int main()
{
// This is dynamic allocated chars array
char* message = "Hello World!";
message = code(message);
printf("%s\n", message);
message = decode(message);
printf("%s\n", message);
}
I need to use strtok to read in a first and last name and seperate it. How can I store the names where I can use them idependently in two seperate char arrays?
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="test string.";
char * test;
test = strtok (str," ");
while (test != NULL)
{
printf ("%s\n",test);
test= strtok (NULL, " ");
}
return 0;
}
Here is my take at a reasonably simple tokenize helper that
stores results in a dynamically growing array
null-terminating the array
keeps the input string safe (strtok modifies the input string, which is undefined behaviour on a literal char[], at least I think in C99)
To make the code re-entrant, use the non-standard strtok_r
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char** tokenize(const char* input)
{
char* str = strdup(input);
int count = 0;
int capacity = 10;
char** result = malloc(capacity*sizeof(*result));
char* tok=strtok(str," ");
while(1)
{
if (count >= capacity)
result = realloc(result, (capacity*=2)*sizeof(*result));
result[count++] = tok? strdup(tok) : tok;
if (!tok) break;
tok=strtok(NULL," ");
}
free(str);
return result;
}
int main ()
{
char** tokens = tokenize("test string.");
char** it;
for(it=tokens; it && *it; ++it)
{
printf("%s\n", *it);
free(*it);
}
free(tokens);
return 0;
}
Here is a strtok-free reimplementation of that (uses strpbrk instead):
char** tokenize(const char* str)
{
int count = 0;
int capacity = 10;
char** result = malloc(capacity*sizeof(*result));
const char* e=str;
if (e) do
{
const char* s=e;
e=strpbrk(s," ");
if (count >= capacity)
result = realloc(result, (capacity*=2)*sizeof(*result));
result[count++] = e? strndup(s, e-s) : strdup(s);
} while (e && *(++e));
if (count >= capacity)
result = realloc(result, (capacity+=1)*sizeof(*result));
result[count++] = 0;
return result;
}
Do you need to store them separately? Two pointers into a modified char array will yield two separate perfectly usable strings.
That is we transform this:
char str[] ="test string.";
Into this:
char str[] ="test\0string.";
^ ^
| |
char *s1 ----- |
char *s2 -----------
.
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="test string.";
char *firstname = strtok(str, " ");
char *lastname = strtok(NULL, " ");
if (!lastname)
lastname = "";
printf("%s, %s\n", lastname, firstname);
return 0;
}
What about using strcpy:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX_NAMES 2
int main ()
{
char str[] ="test string.";
char *names[MAX_NAMES] = { 0 };
char *test;
int i = 0;
test = strtok (str," ");
while (test != NULL && i < MAX_NAMES)
{
names[i] = malloc(strlen(test)+1);
strcpy(names[i++], test);
test = strtok (NULL, " ");
}
for(i=0; i<MAX_NAMES; ++i)
{
if(names[i])
{
puts(names[i]);
free(names[i]);
names[i] = 0;
}
}
return 0;
}
It contains much clutter to maintain a complete program and clean its resources, but the main point is to use strcpy to copy each token into its own string.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char** split(const char *str, const char *delimiter, size_t *len){
char *text, *p, *first, **array;
int c;
char** ret;
*len = 0;
text=strdup(str);
if(text==NULL) return NULL;
for(c=0,p=text;NULL!=(p=strtok(p, delimiter));p=NULL, c++)//count item
if(c==0) first=p; //first token top
ret=(char**)malloc(sizeof(char*)*c+1);//+1 for NULL
if(ret==NULL){
free(text);
return NULL;
}
strcpy(text, str+(first-text));//skip until top token
array=ret;
for(p=text;NULL!=(p=strtok(p, delimiter));p=NULL){
*array++=p;
}
*array=NULL;
*len=c;
return ret;
}
void free4split(char** sa){
char **array=sa;
if(sa!=NULL){
free(array[0]);//for text
free(sa); //for array
}
}
int main(void){
char str[] ="test string.";
char **words;
size_t len=0;
int i;
words = split(str, " \t\r\n,.", &len);
/*
for(char **wk = words; *wk ;wk++){
printf("%s\n", *wk);
}
*/
for(i = 0;i<len;++i){
printf("%s\n", words[i]);
}
free4split(words);
return 0;
}
/* result:
test
string
*/
Copy the results from strtok to a new buffer using a function such as
/*
* Returns a copy of s in freshly allocated memory.
* Exits the process if memory allocation fails.
*/
char *xstrdup(char const *s)
{
char *p = malloc(strlen(s) + 1);
if (p == NULL) {
perror("memory allocation failed");
exit(1);
}
strcpy(p, s);
return p;
}
Don't forget to free the return values when you're done with them.
IMO, you don't need (and probably don't want) to use strtok at all (as in, "for this, or much of anything else"). I think I'd use code something like this:
#include <string.h>
#include <stdlib.h>
static char *make_str(char const *begin, char const *end) {
size_t len = end-begin;
char *ret = malloc(len+1);
if (ret != NULL) {
memcpy(ret, begin, len);
ret[len]='\0';
}
return ret;
}
size_t tokenize(char *tokens[], size_t max, char const *input, char const *delims) {
int i;
char const *start=input, *end=start;
for (i=0; *start && i<max; i++) {
for ( ;NULL!=strchr(delims, *start); ++start)
;
for (end=start; *end && NULL==strchr(delims, *end); ++end)
;
tokens[i] = make_str(start, end);
start = end+1;
}
return i;
}
#ifdef TEST
#define MAX_TOKENS 10
int main() {
char *tokens[MAX_TOKENS];
int i;
size_t num = tokenize(tokens, MAX_TOKENS, "This is a longer input string ", " ");
for (i=0; i<num; i++) {
printf("|%s|\n", tokens[i]);
free(tokens[i]);
}
return 0;
}
#endif
U can do something like this too.
int main ()
{
char str[] ="test string.";
char * temp1;
char * temp2;
temp1 = strtok (str," ");
temp2 = strchr(str, ' ');
if (temp2 != NULL)
temp2++;
printf ("Splitted string :%s, %s\n" , temp1 , temp2);
return
}