This is a very simple question and mistake that I'm making but can anyone explain how I could use sprintf to add to a argv value?
On the command line, I have a file name say data.new.txt (but in my scenario I don't know the name of the file) how can I write to a new file that is named data.new.output.txt
I don't want to create a new file with a different name or update the new file, because this is program will output about 100+ files and that's the specification.
int main(int argc, char * argv[]){
char buffer[100];
sprintf(buffer, "%s.decoded", argv[1]);
printf("%s\n", buffer);
}
Cheers!
Here is a C99 (it uses snprintf()) program for you. Have fun!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *buildname(const char *old, const char *newpart) {
char *dot;
char *buf = NULL;
dot = strrchr(old, '.');
if (dot) {
size_t len;
len = snprintf(NULL, 0, "%.*s%s.%s",
(int)(dot - old) + 1, old, newpart, dot + 1);
buf = malloc(len + 1);
if (buf) {
snprintf(buf, len + 1, "%.*s%s.%s",
(int)(dot - old) + 1, old, newpart, dot + 1);
}
}
return buf;
}
int main(void) {
char *p, *q;
q = "data.new.txt";
p = buildname(q, "output");
if (p) printf("%s ==> %s\n", q, p);
else printf("%s ==> (no dots)\n", q);
free(p);
q = "rrrrrrrrrrrr";
p = buildname(q, "aaa");
if (p) printf("%s ==> %s\n", q, p);
else printf("%s ==> (no dots)\n", q);
free(p);
q = "a.b.c.d.e.f.g.h.i.j.k.l";
p = buildname(q, "Q.Q");
if (p) printf("%s ==> %s\n", q, p);
else printf("%s ==> (no dots)\n", q);
free(p);
return 0;
}
Related
Through a tcp socket I get a string like this: "SmallTitle fromhost 9595".
Upon reciving it I would like to divide it in to a struct so it's easier to work with.
This is what I have come up with. But there are problems. 1 it is nasty. 2 When printing the struct in the end i recieve garbage output after the string. See output example at the bottom. Should not printf stop at '\0'? Then it might be missing such.
struct recieved {
char what[50];
char from[50];
int value;
};
int main(int argc, char const *argv[]) {
struct recieved leaderRec;
char *word;
char buf[] = "leadervalue host 9569"; //Example recieved input from socket.
word = (char *) malloc(sizeof(char) * 50);
int i = 0;
int count = 1;
do{
if((buf[i] == ' ') || (buf[i+1] == '\0')){
//End of word
//word[strlend(word)+1] = '\0';
//printf("%s\n", word);
if(count == 3){
//The value is here
//get the last number
strncat(word,&buf[i], 1);
leaderRec.value = atoi(word);
//printf("%d\n", value);
}
if(count == 1)
strncpy(leaderRec.what, word, strlen(word));
else if(count == 2)
strncpy(leaderRec.from, word, strlen(word));
free(word);
word = (char *) malloc(sizeof(char) * 50);
count++;
}
else {
//printf("%d\n",i );
//printf("%s\n", &buf[i]);
strncat(word,&buf[i], 1);
}
//printf("%s", &buf[i]);
//printf("%d -", i);
i++;
} while(buf[i] != '\0');
printf("%s\n", leaderRec.what);
printf("%s\n", leaderRec.from);
printf("%d\n", leaderRec.value);
return 0;
}
Output:
leadervalue
host__vdso_get
9569
Any better ways to do this?
How would I avoid the garbage output at the second print in the example output?
But there are problems. 1 it is nasty. 2 When printing the struct in
the end i recieve garbage output after the string.
The "garbage" prints, as have been noted in the comments, are because you are not properly null terminating your strings. For instance, you are not initializing word to an empty string (single null character) before calling strncat.
Any better ways to do this?
Most certainly. I'd suggest using strtok as so:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct received {
char what[50];
char from[50];
int value;
};
int main(void)
{
char buf[] = "leadervalue host 9569";
struct received leaderRec;
/* Initialize leaderRec here */
memset(&leaderRec, 0, sizeof(leaderRec));
char *s = strdup(buf);
char *p = strtok(s, " ");
if (p != NULL) {
strncpy(leaderRec.what, p, sizeof(leaderRec.what));
p = strtok(NULL, " ");
}
if (p != NULL) {
strncpy(leaderRec.from, p, sizeof(leaderRec.from));
p = strtok(NULL, " ");
}
if (p != NULL) {
leaderRec.value = atoi(p);
}
free(s);
printf("%s %s %d\n", leaderRec.what, leaderRec.from, leaderRec.value);
return 0;
}
I have a string in my program where in which it need to be altered with another string value before a "/".
Source String : qos-tree/output_rate
Target String : qos-tree-2/output_rate
#include <stdio.h>
#include <string.h>
void append(char* s, char c)
{
int len = strlen(s);
s[len] = c;
s[len+1] = '\0';
}
int main(void)
{
char str[256] = "qos-tree/output_rate";
char c = "a";
append(str, c);
printf("%s\n", str);
return 0;
}
This is what i have done so far,I think the logic is wrong here.Can anyone guide me to correct it?
Once the execution is completed the source string should have a "-2" before the "/"
void insert_before_ch(char *s, const char *ins, char c){
char *p = strchr(s, c);
if(p){
size_t len = strlen(ins);
memmove(p + len, p, strlen(p)+1);
memcpy(p, ins, len);
}
}
int main(void){
char str[256] = "qos-tree/output_rate";
insert_before_ch(str, "-2", '/');
printf("%s\n", str);
return 0;
}
In your attempt, you don't look for a slash and I do not see any "-2" anywhere.
Try this instead:
#include <stdio.h>
#include <string.h>
void append(char* s, char del, char* substring) {
char origin[256];
strcpy(origin, s);
int i = 0, j = 0, z = 0;
for(; origin[i]; ++i) {
if(origin[i] != del) {
s[j++] = origin[i];
} else {
for(; substring[z]; ++z) {
s[j++] = substring[z];
}
s[j++] = origin[i];
}
}
s[j] = '\0';
}
int main(void) {
char str[256] = "qos-tree/output_rate";
char del = '/';
char* substring = "-2";
append(str, del, substring);
printf("%s\n", str);
return 0;
}
The logic is that inside the function we use origin array to remember the actual contents of the array and then we copy from origin to s (which is the actual array of main()). If we find our delimiter del, then we copy the substring in that position and continuing with copying.
Note that the length of the array should be enough to store the resulted string. In this case, it is.
I think you should make your function work with dynamic allocation, because inserting characters into the string will make the resulting string larger, so this is my suggestion
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
void insert(char **str, char chr, unsigned int position)
{
int length;
char *ptr;
if (str == NULL)
return;
length = strlen(*str);
if (position >= length)
return;
ptr = realloc(*str, 2 + length);
if (ptr == NULL)
return;
*str = ptr;
memmove(ptr + position + 1, ptr + position, length - position + 1);
ptr[position] = chr;
}
int main(void)
{
const char *source = "qos-tree/output_rate";
size_t length = strlen(source);
char *str = malloc(1 + length);
if (str == NULL)
return -1;
strcpy(str, source);
insert(&str, '-', 8);
insert(&str, '2', 9);
printf("%s\n", str);
free(str);
return 0;
}
first of all thist char c = "a" should be replace with this char c = 'a'; because c is a character not a string
as for your problem I didn't realy see the relation between what your code is doing with what you said you wanted to do , but here a piece of code to achieve what , I think , you want to do :
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
void append(char* str , char c)
{
char firststr[60];
char therest[30];
strcpy(firststr , strtok(str , "/"));
strcpy(therest , strtok(NULL , "/"));
strcat(firststr , &c);
strcat(firststr , "/");
strcat(firststr , therest);
strcpy(str , firststr);
}
int main(void)
{
char str[60] = "qos-tree/output_rate";
char c = '2';
append(str , c);
printf("%s\n" , str);
}
there you go I think this is what you wanted to do you can modify the array sizes to fit your needs
I have two strings that I would like to combine, removing duplicate substrings. Note that every two consecutive numbers constitute a substring. Consider string str1 and str2:
str1 = "#1#.1.2.3#1#.6.7.8"
str2 = "#1#.6.7.8#1#.5.6"
I would like to produce a combined string as:
comboStr = "#1#.1.2.3#1#.6.7.8#1#.5.6" (i.e. I removed the duplicate #1#.6.7.8).
I have written a small function that does this:
char *combine (char *nodehashkey ,char *ngbrhashkey)
{
char *suffix, *combo_hashkey;
char prefix[5], token[15];
short qid;
short len = strlen(nodehashkey);
combo_hashkey = (char*) malloc(sizeof(char) * (len+1));
strcpy(combo_hashkey, nodehashkey);
short offset = len;
sscanf(nodehashkey, "#%hd#", &qid);
sprintf(prefix, "#%hd#", qid);
printf("prefix: %s\n", prefix);
suffix = strtok(ngbrhashkey, prefix);
while (suffix != NULL)
{
strcpy(token, prefix);
strcpy(token + strlen(prefix), suffix);
int token_len = strlen(token);
if(strstr(nodehashkey, token) == NULL)
{
if(!(combo_hashkey = (char*) realloc (
combo_hashkey, sizeof(char) * (offset+token_len+1))))
printf("malloc failed!");
strncpy(combo_hashkey + offset, token, token_len+1);
offset += token_len;
combo_hashkey[offset] = '\0';
}
suffix = strtok(NULL, prefix);
}
return combo_hashkey;
}
In order to test it, I have tried the following. While, the first two calls to combine produce the correct combo string, the third call doesn't. In stead of producing #1#.1.6#1#.2.4#1#.3.5, it's producing #1#.1.6#1#.2.4#1#.6#1#.3.5
int main (int argc, char *argv[])
{
char *str1 = malloc(sizeof(char) * 8);
strcpy(str1, "#1#.1.6");
char *str2= malloc(sizeof(char) * 8);
strcpy(str2, "#1#.2.4");
char *str3 = malloc(sizeof(char) * 8);
strcpy(str3, "#1#.3.5");
str2 = combine(str1, str2);
str3 = combine(str1, str3);
char *weird = combine(str2, str3);
printf("weird: %s\n", weird);
}
I have traced the function again and I can not spot where the extra #1#.6 comes from.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *combine (const char *nodehashkey, const char *ngbrhashkey){
int i, dup, len, pos_count = 0;
const char *p1, *p2, *pos[64];
char *combo_hashkey, *p3;
if(!nodehashkey || !ngbrhashkey)
return NULL;
//store key position
pos[0] = p1 = nodehashkey;
while(*p1){
sscanf(p1, "#%*d#%*[.0123456789]%n", &len);
pos[++pos_count] = (p1 += len);
}
len = p1 - nodehashkey;
p2 = ngbrhashkey;
p3 = combo_hashkey = malloc(len + strlen(p2) + 1);
memcpy(p3, nodehashkey, len);
p3 += len;
while(*p2){
sscanf(p2, "#%*d#%*[.0123456789]%n", &len);
for(dup=i=0;i<pos_count;++i){
if(pos[i+1]-pos[i] == len && strncmp(pos[i], p2, len)==0){
dup = 1;
break;
}
}
if(!dup){
memcpy(p3, p2, len);
p3 += len;
}
p2 += len;
}
*p3 = '\0';
return combo_hashkey;
}
int main(){
char *str1, *str2, *str3;
str1 = combine("#1#.1.2.3#1#.6.7.8", "#1#.6.7.8#1#.5.6");
printf("%s\n", str1);//#1#.1.2.3#1#.6.7.8#1#.5.6
free(str1);
str2 = combine("#1#.1.6", "#1#.2.4");
str3 = combine("#1#.1.6", "#1#.3.5");
printf("str2:%s\n", str2);
printf("str3:%s\n", str3);
char *weird = combine(str2, str3);
printf("weird: %s\n", weird);//weird: #1#.1.6#1#.2.4#1#.3.5
free(str2);free(str3);free(weird);
return 0;
}
I'm reading a file with the following format:
/* ...more text above */
[Text=WORKING CharacterOffsetBegin=73516 CharacterOffsetEnd=73523 PartOfSpeech=VBG
Lemma=work] [Text=MEN CharacterOffsetBegin=73524 CharacterOffsetEnd=73527
PartOfSpeech=NNS Lemma=man] [Text=OF CharacterOffsetBegin=73528
CharacterOffsetEnd=73530 PartOfSpeech=IN Lemma=of] [Text=ALL
CharacterOffsetBegin=73531 CharacterOffsetEnd=73534 PartOfSpeech=NN Lemma=all]
[Text=COUNTRIES CharacterOffsetBegin=73535 CharacterOffsetEnd=73544 PartOfSpeech=NNS
Lemma=country] [Text=, CharacterOffsetBegin=73544 CharacterOffsetEnd=73545
PartOfSpeech=, Lemma=,] [Text=UNITE CharacterOffsetBegin=73546
CharacterOffsetEnd=73551 PartOfSpeech=VB Lemma=unite] [Text=!
CharacterOffsetBegin=73551 CharacterOffsetEnd=73552 PartOfSpeech=. Lemma=!]
/* ...more text below */
What i want to do is to extract into an array the strings given by Text= and Lemma=. For example, for the text above the output would be:
WORKING
work
MEN
man
OF
of
And so on. What i've tried:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE 4096
int main()
{
FILE *fp;
fp = fopen("moby.txt.out", "r");
char *linha = malloc(MAX_LINE);
int s, t;
char lemma[100];
while(fgets(linha, MAX_LINE, fp))
{
if(sscanf(linha, "Sentence #%d (%d tokens):", &s, &t))
{
/*printf("%d\n", t);*/
}
else if(sscanf(linha, "Lemma=%s", lemma))
{
printf("%s", lemma);
}
}
fclose(fp);
return 0;
}
I can't use external libs.
I know regex is not part of C language, so any help is welcome.
Thanks!
And anyways you don't even need regexes. Nor scanf(). A simple solution is using strstr().
const char *s = "[Text=WORKING CharacterOffsetBegin=73516 CharacterOffsetEnd=73523 PartOfSpeech=VBG \
Lemma=work] [Text=MEN CharacterOffsetBegin=73524 CharacterOffsetEnd=73527 \
PartOfSpeech=NNS Lemma=man]";
const char *p = s;
while ((p = strstr(p, "Text=")) != NULL) {
p += 5;
const char *t = strchr(p, ' ');
printf("%.*s\n", (int)(t - p), p);
p = strstr(t + 1, "Lemma=") + 6;
t = strchr(p, ']');
printf("%.*s\n", (int)(t - p), p);
p = t + 1;
}
In C how can I separate a char array by a delimiter? Or is it better to manipulate a string? What are some good C char manipulation functions?
#include<string.h>
#include<stdio.h>
int main()
{
char input[16] = "abc,d";
char *p;
p = strtok(input, ",");
if(p)
{
printf("%s\n", p);
}
p = strtok(NULL, ",");
if(p)
printf("%s\n", p);
return 0;
}
you can look this program .First you should use the strtok(input, ",").input is the string you want to spilt.Then you use the strtok(NULL, ","). If the return value is true ,you can print the other group.
Look at strtok(). strtok() is not a re-entrant function.
strtok_r() is the re-entrant version of strtok(). Here's an example program from the manual:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
char *str1, *str2, *token, *subtoken;
char *saveptr1, *saveptr2;
int j;
if (argc != 4) {
fprintf(stderr, "Usage: %s string delim subdelim\n",argv[0]);
exit(EXIT_FAILURE);
}
for (j = 1, str1 = argv[1]; ; j++, str1 = NULL) {
token = strtok_r(str1, argv[2], &saveptr1);
if (token == NULL)
break;
printf("%d: %s\n", j, token);
for (str2 = token; ; str2 = NULL) {
subtoken = strtok_r(str2, argv[3], &saveptr2);
if (subtoken == NULL)
break;
printf(" --> %s\n", subtoken);
}
}
exit(EXIT_SUCCESS);
}
Sample run which operates on subtokens which was obtained from the previous token based on a different delimiter:
$ ./a.out hello:word:bye=abc:def:ghi = :
1: hello:word:bye
--> hello
--> word
--> bye
2: abc:def:ghi
--> abc
--> def
--> ghi
One option is strtok
example:
char name[20];
//pretend name is set to the value "My name"
You want to split it at the space between the two words
split=strtok(name," ");
while(split != NULL)
{
word=split;
split=strtok(NULL," ");
}
You could simply replace the separator characters by NULL characters, and store the address after the newly created NULL character in a new char* pointer:
char* input = "asdf|qwer"
char* parts[10];
int partcount = 0;
parts[partcount++] = input;
char* ptr = input;
while(*ptr) { //check if the string is over
if(*ptr == '|') {
*ptr = 0;
parts[partcount++] = ptr + 1;
}
ptr++;
}
Note that this code will of course not work if the input string contains more than 9 separator characters.
I came up with this.This seems to work best for me.It converts a string of number and splits it into array of integer:
void splitInput(int arr[], int sizeArr, char num[])
{
for(int i = 0; i < sizeArr; i++)
// We are subtracting 48 because the numbers in ASCII starts at 48.
arr[i] = (int)num[i] - 48;
}
This is how I do it.
void SplitBufferToArray(char *buffer, char * delim, char ** Output) {
int partcount = 0;
Output[partcount++] = buffer;
char* ptr = buffer;
while (ptr != 0) { //check if the string is over
ptr = strstr(ptr, delim);
if (ptr != NULL) {
*ptr = 0;
Output[partcount++] = ptr + strlen(delim);
ptr = ptr + strlen(delim);
}
}
Output[partcount++] = NULL;
}
In addition, you can use sscanf for some very simple scenarios, for example when you know exactly how many parts the string has and what it consists of. You can also parse the arguments on the fly. Do not use it for user inputs because the function will not report conversion errors.
Example:
char text[] = "1:22:300:4444:-5";
int i1, i2, i3, i4, i5;
sscanf(text, "%d:%d:%d:%d:%d", &i1, &i2, &i3, &i4, &i5);
printf("%d, %d, %d, %d, %d", i1, i2, i3, i4, i5);
Output:
1, 22, 300, 4444, -5
For anything more advanced, strtok() and strtok_r() are your best options, as mentioned in other answers.