C split string into chunks using sscanf? - c

I'm trying to write a program to split a string into the first 3 characters, the next 3 characters, and then the last 3 characters for the specific string.
int main(int argc, char *argv[])
{
char str[9] = "AbcDefGhi";
char first[3], second[3], third[3];
int ret;
ret = sscanf(str, "%3s%3s%3s", first, second, third);
printf("# variables: %i\n", ret);
printf("1: %s\n", first);
printf("2: %s\n", second);
printf("3: %s\n", third);
printf("whoops");
return 0;
}
But when I run it, the output is
# variables: 3
1: AbcDefGhi
2: DefGhi
3: Ghi
whoops
And I want
# variables: 3
1: Abc
2: Def
3: Ghi
whoops
Any help is appreciated.

man scanf:
String input conversions store a terminating null byte ('\0') to mark the end of the input; the maximum field width does not include this terminator.
That is, the buffer to store the string needs to be at least one byte larger than the maximum field width to account for the NUL terminator. So increase the size of all your arrays to account for the NUL terminator.
char str[] = "AbcDefGhi";
char first[4], second[4], third[4];

I'm not sure if you need to do it without any functions from libraries, but I have created a code that is doing exactly what you want.
Let us know if it's to complicated for you.
#include <stdio.h>
#include <stdlib.h>
char *split(const char *str, size_t size){
static const char *p=NULL;
char *temp;
int i;
if(str != NULL) p=str;
if(p==NULL || *p=='\0') return NULL;
temp=(char*)malloc((size+1)*sizeof(char));
for(i=0;*p && i<size;++i){
temp[i]=*p++;
}
temp[i]='\0';
return temp;
}
int main(){
char *p = "AbcDefGhi";
char *temp[5];
int i,j;
for(i=0;NULL!=(p=split(p, 3));p=NULL)
temp[i++]=p;
for(j=0;j<i;++j){
printf("%d: %s\n",j, temp[j]);
free(temp[j]);
}
printf("whoops");
return 0;
}

Related

Using strncmp by checking only a variable single element of a char array

I am trying to write a code which compares the letters of a char array one by one against a determined letter (letter 'l'). When this is the case in the output string, there are two 'l's. For instance, "lily" should become "llilly". I fail to see how to implement this in C because something like this :
strncmp (word[indx],'l',1) //where indx is an iterator of the char array 'word'
is not valid because the first argument should be 'word' but then there is no way to iterate through 'word'.
And of course if we wrote:
strncmp (word,'l',indx)
The problem is that now we are checking more than one letter at a time after indx becomes equal or larger than 2 and what we really want is to check one character at a time.
This is my code so far:
#include <stdio.h>
#include <string.h>
const char* ModifyString (char word []);
int main(){
char word[6]="Hello";
printf("The result is %s \n", ModifyString(word));
return 0;
}
const char* ModifyString (char word []) {
size_t lengthString=strlen(word);
char modifiedString[lengthString*2+1]; //to fit the nul terminator and all the 'l's in case the word only contained 'l's.
int indxModWord=0;
for (int indx=0; indx<lengthString;indx++) {
//This line does not express what I want to do:
if (strncmp(word,"l",indx)==0) {
modifiedString[indxModWord]=word[indx];
indxModWord++;
}
// if 'l' in word make it appear twice in the output string
else {
modifiedString[indxModWord]='l';
indxModWord++;
modifiedString[indxModWord]='l';
indxModWord++;
}
}
printf("%s", modifiedString);
}
Does anyone has any idea how I should do this in C?
Simply compare the characters as in other answers.
But of course, you can use strncmp to compare the chars if you wish.
strncmp (&word[indx],(char []){'l'},1);
or you can write the function:
int compareCharsUsingStrncmp(const char a, const char b)
{
return strncmp((char[]){a}, (char[]){b}, 1);
}
or
int compareCharsUsingStrncmp(const char a, const char b)
{
return strncmp(&a, &b, 1);
}
Smart compilers will not even call the strncmp :)
compareCharsUsingStrncmp:
movzx eax, dil
movzx esi, sil
sub eax, esi
ret
While traversing the given string, keep a check to see if the current character of the string is you target character (in your case 'l').
Code:
const char* ModifyString (char word [])
{
size_t lengthString=strlen(word);
char modifiedString[lengthString*2+1]; //to fit the nul terminator and all the 'l's in case the word only contained 'l's.
int indxModWord=0;
char targetCharacter = 'l';
for (int indx=0; indx<lengthString; indx++)
{
if (word[indx] != targetCharacter)
{
modifiedString[indxModWord] = word[indx];
indxModWord++;
}
else
{
modifiedString[indxModWord] = targetCharacter;
indxModWord++;
modifiedString[indxModWord] = targetCharacter;
indxModWord++;
}
}
modifiedString[indxModWord] = '\0';
printf("%s", modifiedString);
}
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char *ModifyString (char* word) {
size_t lengthString = strlen(word);
//to fit the nul terminator and all the 'l's in case the word only contained 'l's.
char *modifiedString;
modifiedString=(char*)malloc(lengthString*2+1);
size_t indxModWord=0;
for (int indx=0; indx<lengthString;indx++) {
//This line does not express what I want to do:
if (word[indx] != 'l'){
modifiedString[indxModWord]=word[indx];
indxModWord++;
}
// if 'l' in word make it appear twice in the output string
else {
modifiedString[indxModWord]='l';
indxModWord++;
modifiedString[indxModWord]='l';
indxModWord++;
}
}
return (char *)modifiedString;
}
int main(){
char word[]="Hello";
char *result ;
result = ModifyString(word);
printf("The result is %s \n",result);
return 0;
}
Please check if this is what you were looking for.

Using Pointers and strtok()

I'm building a linked list and need your assistance please as I'm new to C.
I need to input a string that looks like this: (word)_#_(year)_#_(DEFINITION(UPPER CASE))
Ex: Enter a string
Input: invest_#_1945_#_TRADE
Basically I'm looking to build a function that scans the DEFINITION and give's me back the word it relates to.
Enter a word to search in the dictionary
Input: TRADE
Output: Found "TREADE" in the word "invest"
So far I managed to come up using the strtok() function but right now I'm not sure what to do about printing the first word then.
Here's what I could come up with:
char split(char words[99],char *p)
{
p=strtok(words, "_#_");
while (p!=NULL)
{
printf("%s\n",p);
p = strtok(NULL, "_#_");
}
return 0;
}
int main()
{
char hello[99];
char *s = NULL;
printf("Enter a string you want to split\n");
scanf("%s", hello);
split(hello,s);
return 0;
}
Any ideas on what should I do?
I reckon that your problem is how to extract the three bits of information from your formatted string.
The function strtok does not work as you think it does: The second argument is not a literal delimiting string, but a string that serves as a set of characters that are delimiters.
In your case, sscanf seems to be the better choice:
#include <stdlib.h>
#include <stdio.h>
int main()
{
const char *line = "invest_#_1945 _#_TRADE ";
char word[40];
int year;
char def[40];
int n;
n = sscanf(line, "%40[^_]_#_%d_#_%40s", word, &year, def);
if (n == 3) {
printf("word: %s\n", word);
printf("year: %d\n", year);
printf("def'n: %s\n", def);
} else {
printf("Unrecognized line.\n");
}
return 0;
}
The function sscanf examines a given string according to a given pattern. Roughly, that pattern consists of format specifiers that begin with a percent sign, of spaces which denote any amount of white-space characters (including none) and of other characters that have to be matched varbatim. The format specifiers yield a result, which has to be stored. Therefore, for each specifier, a result variable must be given after the format string.
In this case, there are several chunks:
%40[^_] reads up to 40 characters that are not the underscore into a char array. This is a special case of reading a string. Strings in sscanf are really words and may not contain white space. The underscore, however, would be part of a string, so in order not to eat up the underscore of the first delimiter, you have to use the notation [^(chars)], which means: Any sequence of chars that do not contain the given chars. (The caret does the negation here, [(chars)] would mean any sequence of the given chars.)
_#_ matches the first delimiter literally, i.e. only if the next chars are underscore hash mark, underscore.
%d reads a decimal number into an integer. Note that the adress of the integer has to be given here with &.
_#_ matches the second delimiter.
%40s reads a string of up to 40 non-whitespace characters into a char array.
The function returns the number of matched results, which should be three if the line is valid. The function sscanf can be cumbersome, but is probably your best bet here for quick and dirty input.
#include <stdio.h>
#include <string.h>
char *strtokByWord_r(char *str, const char *word, char **store){
char *p, *ret;
if(str != NULL){
*store = str;
}
if(*store == NULL) return NULL;
p = strstr(ret=*store, word);
if(p){
*p='\0';
*store = p + strlen(word);
} else {
*store = NULL;
}
return ret;
}
char *strtokByWord(char *str, const char *word){
static char *store = NULL;
return strtokByWord_r(str, word, &store);
}
int main(){
char input[]="invest_#_1945_#_TRADE";
char *array[3];
char *p;
int i, size = sizeof(array)/sizeof(char*);
for(i=0, p=input;i<size;++i){
if(NULL!=(p=strtokByWord(p, "_#_"))){
array[i]=p;//strdup(p);
p=NULL;
} else {
array[i]=NULL;
break;
}
}
for(i = 0;i<size;++i)
printf("array[%d]=\"%s\"\n", i, array[i]);
/* result
array[0]="invest"
array[1]="1945"
array[2]="TRADE"
*/
return 0;
}

possible way to implement array of pointers to string

I had a code which works fine with the integers
#include<stdio.h>
int main()
{
int i;
int* p[5];
printf("Enter the elements to be shorted");
for(i=0;i<=4;i++)
{
scanf("%d\n",&p[i]);
}
for(i=0;i<=4;i++)
{
printf("entered [%d] integers are = %s",i, p[i]);
}
return 0;
}
produce a output
Enter the strings to be shorted1
2
3
4
5
6
enetered [0] string is = 1
enetered [1] string is = 2
enetered [2] string is = 3
enetered [3] string is = 4
enetered [4] string is = 5
but when i change limne int* p[5] to char* p[5] for using it as array of pointers to string and do the necessary changes in the above code, it produces segmentation fault.I read ian a book that we cant do this as some garbage value will be assigned to the array of pointers to string.So what can be the possible way to implement the above code with array of pointers to string.
what i want to do is get the strings as input from users and store them in array of pointers to string and then get them printed at initial stage.I am trying to code for simplest string shorting.
Make sure you reserve room for the characters of the strings:
char p[5][128];
and also make sure you limit the length when reading, so scanf() doesn't write outside the buffer:
if(scanf("%127s", p[i]) == 1)
{
p[i][127] = '\0'; /* Make sure it's terminated. */
}
First of all, the int array definition is wrong in your first test. it should be
int p[5];
Second you have to allocate memory for each pointer in your array. each element in your array char *p[5]; is a pointer.
You can use directly by scanf
char *p[5];
for(i=0;i<=4;i++)
{
scanf("%ms\n",&p[i]);
}
But this is not portable is available only for gcc>gcc2.7
or you have to allocate memory each time before scanf()
char *p[5];
for(i=0;i<=4;i++)
{
p[i]=calloc(100,1);
scanf("%99s\n",p[i]);
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void){
int i;
char *p[5];
printf("Enter the string\n");
for(i=0;i<=4;i++){
char buff[128];
scanf("%127s", buff);
p[i] = strdup(buff);
}
for(i=0;i<=4;i++){
printf("entered [%d] string is = %s\n", i+1, p[i]);
}
for(i=0;i<5;++i) free(p[i]);
return 0;
}

Is there any function available for printing some characters instead of whole strings?

see
char str[] = "hello world";
printf("%s",str);
printf statement prints the all character in string before reaching '\0'
so what if i want to print just 4 1st character of str on stdout?
You can just specify the field width in the printf format string:
#include <stdio.h>
int main(void)
{
const char *s = "Hello world !";
printf("%.4s\n", s);
return 0;
}
or, if you want to specify the field width at run-time:
#include <stdio.h>
int main(void)
{
const char *s = "Hello world !";
const int fw = 4;
printf("%.*s\n", fw, s);
return 0;
}
In either case the output will be:
Hell
You can use %c in your format string:
printf("%c", *s);
prints 'H'
To print an arbitrary char:
printf("%c", s[3]);
prints 'l'
For the first character, you can just use:
printf ("%c", *str); // or
printf ("%c", *(str+0)); // or
printf ("%c", str[0]);
For a different character, just reach out and grab it by using an offset. For the second l at offset 3:
printf ("%c", str[3]); // or
printf ("%c", *(str+3));
For a substring, you can use a combination of that method along with the maximum field width feature of printf:
printf ("%.2s", str+3); // prints "lo"
With all these solutions, you want to make sure you don't start on the wrong side of the null terminator. That wouldn't be a good thing :-)
If you want a generalised solution that will work for any string, and is relatively safe in terms of finding the starting point, you can use:
void outSubstr (FILE *fh, char *str, size_t start, size_t sz, int padOut) {
if (start >= strlen (str)) {
if (padOut)
fprintf (fh, "%*s", sz, "");
return;
}
if (padOut)
fprintf (fh, "%-*.*s", sz, sz, str + start);
else
fprintf (fh, "%-.*s", sz, str + start);
}
The parameters are as follows:
fh is the file handle to write to.
str is the start of the string.
start is the offset to start printing from.
sz is the maximum number of characters to print.
padOut is a flag indicating that sz is also the minimum size. Output will be padded with spaces on the right if there are not enough characters in the string to satisfy the size.
This will print up to 4 characters.
printf("%.4s", str);
there is also a "substr()" function
that return the substring from complete string.
example
printf("%s",substr(str,0,4));
it has syntax like this
substr(arrayName,charStartingPosition, lengthOfCharacters);
i hope this is easy to understand and no need to write more than 1 statement.
Really less painful for the system :
int main(void)
{
char c;
c = 'z';
write(1, &c, 1);
}
No need for heavy stdio here
Then you can ...
char *s = "Hello, World!";
write(1, s, numberOfChars);
Or if you really want to do it char by char:
void printnchars(char *s, int n)
{
int i;
i = 0;
while (i <= n)
{
write(1, s + i, 1);
i++;
}
}
numOfChars = 4;
printf("%.*s\n", numOfChars, "Hello, world!");
Where numOfChars is the quantity of characters that you want to print.

Strings in C Language

How can you code this in C language if the output is like this? I need strings format of the code because our topic is strings.
#include <stdio.h>
#include <stdlib.h>
void main()
{
char my_string[50];
printf("Enter a word:");
scanf("%s", my_string);
printf("Enter a word:");
scanf("%s", my_string);
// Some unknown code here...
// this part is my only problem to solve this.
getch();
}
Output:
Hello -> (user input)
World -> (user input)
HWeolrllod -> (result)
Okay, you need to do some investigating. We don't, as a general rule, do people's homework for them since:
it's cheating.
you'll probably get caught out if you copy verbatim.
it won't help you in the long run at all.
The C library call for user input that you should use is fgets, along the line of:
char buffer[100];
fgets (buffer, sizeof(buffer), stdin);
This will input a string into the character array called buffer.
If you do that with two different buffers, you'll have the strings in memory.
Then you need to create pointers to them and walk through the two strings outputting alternating characters. Pointers are not an easy subject but the following pseudo-code may help:
set p1 to address of first character in string s1
set p1 to address of first character in string s1
while contents of p1 are not end of string marker:
output contents of p1
add 1 to p1 (move to next character)
if contents of p2 are not end of string marker:
output contents of p2
add 1 to p2 (move to next character)
while contents of p2 are not end of string marker:
output contents of p2
add 1 to p2 (move to next character)
Translating that into C will take some work but the algorithm is solid. You just need to be aware that a character pointer can be defined with char *p1;, getting the contents of it is done with *p1 and advancing it is p = p + 1; or p1++;.
Short of writing the code for you (which I'm not going to do), there's probably not much else you need.
void main()
{
char my_string1[50],my_string2[50]; int ptr;
ptr=0;
printf("Enter a word : ");
scanf("%s",my_string1);
printf("enter a word");
scanf("%s",my_string2);
while(my_string1[ptr]!='\0' && my_string2[ptr]!='\0')
{
printf("%c%c",my_string1[ptr],my_string2[ptr]);
ptr++;
}
if(my_string1[ptr]!='\0')
{
while(my_string1[ptr]!='\0')
{ printf("%c",my_string1[ptr]);
ptr++;
}
}
else
{
while(my_string2[ptr]!='\0')
{printf("%c",my_string2[ptr]);
ptr++;
}
}
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main()
{
char my_string1[50],my_string2[50];
int i,l1=1,l2=0;
printf("Enter a word:");
scanf("%s", my_string1);
printf("Enter a word:");
scanf("%s", my_string2);
l1=strlen(my_string1); /* Length of 1st string */
l2=strlen(my_string2); /* Length of 2nd string */
if(l1==l2)
{
for(i=0;i<l1;i++)
{
printf("%c%c",my_string1[i],my_string2[i]);
}
}
else
{
printf("Length of the entered strings do not match");
}
}
This is your required code.
You can see that output needs to be a String containing all chars of User String1 and User String2 one by one...
You can do this like...
//add #include<String.h>
int l1=strlen(s1);
int l2=strlen(s2);
if(l1!=l2)
{
printf("length do not match");
return 0;
}
char ansstr[l1+l2];
int i,j=0,k=0;
for(i=0;i<l1+l2;i=i+2)
{
ansstr[i]=s1[j];
ansstr[i+1]=s2[k];
j++;
k++;``
}
//ansstr is your answer
Ok, here's your code. Come on guys, if he asked here it means he can't solve this.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char str1[] = "abcdefghijklmopq";
char str2[] = "jklm";
int len1 = strlen(str1);
int len2 = strlen(str2);
int c1 = 0, c2 = 0;
int max = (len1 > len2) ? len1 : len2 ;
char *result = malloc(len1 + len2);
for(c1 = 0; c1 <= max; c1++) {
if(c1 < len1)
result[c2++] = str1[c1];
if(c1 < len2)
result[c2++] = str2[c1];
}
result[c2] = 0;
printf("\n%s\n", result);
return 0;
}
Basically the loop picks up a character from str1 and appends it to result. Then it picks a character, which stands in the same position as the first from str2 and appends it to result, just as before. I increment c2 by 2 every time because I'm adding 2 chars to result. I check if c1 is bigger that the length of the strings because I want to copy only the characters in the string without the terminating \0. If you know that your strings have the same length you can omit these ifs.

Resources