I'm trying to do, a program that prints a string like this
char str[] = "This is a test string";
And then get this output
This
is
a
test
string
All this without using neither loop nor recursion. It is possible to do this?
As noted in the comments to this answer, goto is just a bad replacement for for, while, etc. Technically, it is a loop, so writing the program without looping is pretty much impossible.
Furthermore, as others have mentioned, printf and similar screen I/O functions most probably also uses a loop, so "All this without using loop nor recursion [...]" should be pretty hard.
Writing the "printing each word on a seperate line" part as a general solution1 could be done using the goto keyword, though. The following program replaces every occurence of ' ' with a \n and prints the string afterwards:
size_t i = 0;
loop_beg:
if (!str[i])
goto loop_end;
if (str[i] == ' ')
str[i] = '\n';
++i;
goto loop_beg;
loop_end:
printf("%s\n", str);
Note: this probably compiles down to a loop at the Assembly level and is then roughly equivalent to the for-loop construct in C but I'll ignore that.
Related to that, you should read (or at least skim) Edsger Dijsktra's (Dutch guy, invented semaphores, co-wrote the OS "THE") "Go To Statement Considered Harmful".
1 to just print every word of this particular string on one line each neither of this is required, obviously.
you can use strtok for this but it is implemented with the help of loop and its pretty neat
char str[] ="This is a test string";
char * pch;
pch = strtok (str," ");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, " "); <-- delimiter to seperate the string
}
#include <stdio.h>
int main(void)
{
char str[] = " this is a string";
char *ptr = str;
bool init = 0;
int n = 0;
BlackLabel:
if( *ptr == '\0' )
goto exit;
n++;
if( *ptr == ' ' )
n = 0;
if( n == 1 )
{
if( init )
{
putc('\n',stdout);
}
}
if( n > 0 )
{
init = 1;
printf("%c",*ptr);
}
*ptr++;
goto BlackLabel;
exit:
putc('\n',stdout);
return 0;
}
I propose to replace space with new line indicator.
public string f(string input)
{
str = str.Replace(" ", "\n");
return str;
}
This fuction will return text with each word one below another.
EDIT:
Note that this will be always used with loops. Even if not called directly, your application just must to go throught all characters in range.
Related
Previous question was : what am I doing wrong that strtok does right in splitting a string. Also separating the strtok to a function suddenly doesn't produce correct result?
This is the first time that I ask a question in stackoverflow so forgive me if this is wordy and incoherent. The last part of the question is elaborated at the bottom part of this question body.
So, I was doing a course assessment assigned by my college, in that, one question is :
Remove duplicate words and print only unique words
Input : A single sentence in which each word separated by a space
Output : Unique words separated by a space [Order of words should be same as in input]
Example:
Input : adc aftrr adc art
Output : adc aftrr art
Now, I have the solution which is to split the string on whitespaces and adding the word to a array(set) if it is not already exists, but it is the implementation part that makes me to plug my hair out
#include <stdio.h>
#include <string.h>
#define MAX 20
int exists(char words[][MAX], int n, char *word){ // The existence check function
for(int i=0;i < n;i++)
if(strcmp(words[i],word) == 0)
return 1;
return 0;
}
void removeDuplicateOld(char*);
void removeDuplicateNew(char*);
int main(){
char sentence[MAX*50] = {0}; //arbitary length
fgets(sentence,MAX*50,stdin);
sentence[strcspn(sentence,"\n")]=0;
printf("The Old One : \n");
removeDuplicateOld(sentence);
printf("\nThe New One : \n");
removeDuplicateNew(sentence);
}
The fucntion that uses strtok to split string :
void removeDuplicateNew(char *sentence){
char words[10][MAX] = {0};
int wi=0;
char *token = strtok(sentence," ");
while(token != NULL){
if(exists(words,wi,token)==0) {
strcpy(words[wi++],token);
}
token = strtok(NULL," ");
}
for(int i=0;i<wi;i++) printf("%s ",words[i]);
}
The old function that uses my old method (which is constructing a word until I hit whitespace) :
void removeDuplicateOld(char *sentence){
char objects[10][MAX] = {0}; //10 words with MAX letters
char tword[MAX];
int oi=0, si=0, ti=0;
while(sentence[si]!='\0'){
if(sentence[si] != ' ' && sentence[si+1] != '\0')
tword[ti++] = sentence[si];
else{
if(sentence[si+1] == '\0')
tword[ti++]=sentence[si];
tword[ti]='\0';
if(exists(objects,oi,tword) == 0){
strcpy(objects[oi++],tword);
}
ti=0; // The buffer[tword] is made to be overwritten
}
si++;
}
for(int i=0;i<oi;i++)
printf("%s ",objects[i]);
}
Solved : changed if(sentence[si+1] == '\0') to if(sentence[si+1] == '\0' && sentence[si]!=' ')
Here is the output :
input : abc def ghi abc jkl ghi
The Old One :
abc def ghi jkl
The New One :
abc def ghi jkl
Note trailing whitespaces in input and output is not checked as their own driver code doesn't properly handle them while strtok method does and it passes all tests.
Now both methods seems to be producing same results but they are indeed producing different outputs according to test cases and in top of that separating strtok method as a separate function[removeDuplicateNew] fails one test case while writing it in main method itself passes all test, see these results :
Old Method Test Case results
Strtok Method as Separate Function Test Case Results
Following Was Moved To A separate Question Thread
When Coded in main method itself :
int main(){
char sentence[MAX*50] = {0}; //arbitary length
fgets(sentence,MAX*50,stdin);
sentence[strcspn(sentence,"\n")] = 0;
char words[10][MAX] = {0};
int wi=0;
char *token = strtok(sentence," ");
while(token != NULL){
if(exists(words,wi,token)==0) {
strcpy(words[wi++],token);
}
token = strtok(NULL," ");
}
for(int i=0;i<wi;i++) printf("%s ",words[i]);
}
Strtok Method as inline code Test Case Results
For the record, it is the same code just placed in main method, so what the heck happens here that when I separate it as a function and pass the string as argument it suddenly isn't working properly.
Also any advice on my question building, wording is appreciated.
Your code...
void removeDuplicateOld(char *sentence){
char objects[10][MAX] = {0}; //10 words with MAX letters
char tword[MAX];
int oi=0, si=0, ti=0;
while(sentence[si]!='\0'){
if(sentence[si] != ' ' && sentence[si+1] != '\0')
tword[ti++] = sentence[si];
else{
// right here have hit SP.
// if SP followed by '\0'
// then append SP to my word... wrong! <=====
if(sentence[si+1] == '\0')
tword[ti++]=sentence[si];
tword[ti]='\0';
This is why the library function strtok() works better than hand rolled code.It has been tested and proven to work as it says it does.
There's a better way to use strtok()
for( char *p = sentence; (p = strtok( p, " \n") ) != NULL; p = NULL )
if( exists( words, wi, p ) == 0 )
strcpy( words[wi++], p );
That's all you need. strtok() will even trim the LF off the buffer for you, no extra charge.
Final suggestion: Instead of a fixed-sized array of pointers to words, you might consider a linked-list (LL) that can easily grow. The function that would append a new word to the end of the list can quietly eat the word if it turns out to be a duplicate found while traversing to append to the end of the LL.
I would like to print the remaining string by a deliminator.
The expected output should be:
String
in
C
int main()
{
/* loop over a string using subscript*/
char *s = "String in C";
char* ps;
ps = s;
while(*ps != ' ')
{
printf("%c",*ps);
ps++;
}
}
I can get the first String.
How can I get the rest of it?
This is not the best solution but it works.
#include <stdio.h>
int main()
{
char *s = "String in C";
char *ps;
ps = s;
while (*ps != '\0')
{
if (*ps == ' ')
{
printf("\n");
*ps++;
}
else
{
printf("%c", *ps);
ps++;
}
}
}
You need to examine the logic of your program.
What you are doing right now is you stop iterating right after the first word, when the first space is encountered; that is what while(*ps != ' ') does.
Instead, you can iterate through the whole string, taking advantage of the fact that a string in C ends with a \0, i.e. while (*ps != '\0').
Inside the while you can first test if the character is a blank, and if it is you can advance the pointer and skip to the next character using continue:
if (*ps == ' ') {
printf("\n");
ps++;
continue;
}
Note that the code also prints a newline for readability. This if should also be first thing in the loop and this way it will also skip trailing blanks.
The rest of the code is what you have now, though you may want to add another newline printf after the while loop.
Is there any efficient (- in terms of performance) way for printing some arbitrary string, but only until the first new line character in it (excluding the new line character) ?
Example:
char *string = "Hello\nWorld\n";
printf(foo(string + 6));
Output:
World
If you are concerned about performance this might help (untested code):
void MyPrint(const char *str)
{
int len = strlen(str) + 1;
char *temp = alloca(len);
int i;
for (i = 0; i < len; i++)
{
char ch = str[i];
if (ch == '\n')
break;
temp[i] = ch;
}
temp[i] = 0;
puts(temp);
}
strlen is fast, alloca is fast, copying the string up to the first \n is fast, puts is faster than printf but is is most likely far slower than all three operations mentioned before together.
size_t writetodelim(char const *in, int delim)
{
char *end = strchr(in, delim);
if (!end)
return 0;
return fwrite(in, 1, end - in, stdout);
}
This can be generalized somewhat (pass the FILE* to the function), but it's already flexible enough to terminate the output on any chosen delimiter, including '\n'.
Warning: Do not use printf without format specifier to print a variable string (or from a variable pointer). Use puts instead or "%s", string.
C strings are terminated by '\0' (NUL), not by newline. So, the functions print until the NUL terminator.
You can, however, use your own loop with putchar. If that is any performance penalty is to be tested. Normally printf does much the same in the library and might be even slower, as it has to care for more additional constraints, so your own loop might very well be even faster.
for ( char *sp = string + 6 ; *sp != '\0'; sp++ ) {
if ( *sp == '\n' ) break; // newline will not be printed
putchar(*sp);
}
(Move the if-line to the end of the loop if you want newline to be printed.)
An alternative would be to limit the length of the string to print, but that would require finding the next newline before calling printf.
I don't know if it is fast enough, but there is a way to build a string containing the source string up to a new line character only involving one standard function.
char *string = "Hello\nWorld\nI love C"; // Example of your string
static char newstr [256]; // String large enough to contain the result string, fulled with \0s or NULL-terimated
sscanf(string + 6, "%s", newstr); // sscanf will ignore whitespaces
sprintf(newstr); // printing the string
I guess there is no more efficient way than simply looping over your string until you find the first \n in it. As Olaf mentioned it, a string in C ends with a terminating \0 so if you want to use printf to print the string you need to make sure it contains the terminating \0 or yu could use putchar to print the string character by character.
If you want to provide a function creating a string up to the first found new line you could do something like that:
#include <stdio.h>
#include <string.h>
#define MAX 256
void foo(const char* string, char *ret)
{
int len = (strlen(string) < MAX) ? (int) strlen(string) : MAX;
int i = 0;
for (i = 0; i < len - 1; i++)
{
if (string[i] == '\n') break;
ret[i] = string[i];
}
ret[i + 1] = '\0';
}
int main()
{
const char* string = "Hello\nWorld\n";
char ret[MAX];
foo(string, ret);
printf("%s\n", ret);
foo(string+6, ret);
printf("%s\n", ret);
}
This will print
Hello
World
Another fast way (if the new line character is truly unwanted)
Simply:
*strchr(string, '\n') = '\0';
If I have a string like:
const char* mystr = "Test Test Bla Bla \n Bla Bla Test \n Test Test \n";
How would I use the newline character '\n', to split the string into an array of strings?
I'm trying to accomplish in C, the thing string.Split() does in C# or boost's string algorithm split does in C++ .
Try to use the strtok function. Be aware that it modifies the source memory so you can't use it with a string literal.
char *copy = strdup(mystr);
char *tok;
tok = strtok(copy, "\n");
/* Do something with tok. */
while (tok) {
tok = strtok(NULL, "\n");
/* ... */
}
free(copy);
The simplest way to split a string in C is to use strtok() however that comes along with an arm's length list of caveats on its usage:
It's destructive (destroys the input string), and you couldn't use it on the string you have above.
It's not reentrant (it keeps its state between calls, and you can only be using it to tokenize one string at a time... let alone if you wanted to use it with threads). Some systems provide a reentrant version, e.g. strtok_r(). Your example might be split up like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (void) {
char mystr[] = "Test Test Bla Bla \n Bla Bla Test \n Test Test \n";
char *word = strtok(mystr, " \n");
while (word) {
printf("word: %s\n", word);
word = strtok(NULL, " \n");
}
return 0;
}
Note the important change of your string declaration -- it's now an array and can be modified. It's possible to tokenize a string without destroying it, of course, but C does not provide a simple solution for doing so as part of the standard library.
Remember that C makes you do all the memory allocation by hand. Remember also that C doesn't really have strings, only arrays of characters. Also, string literals are immutable, so you're going to need to copy it. It will be easier to copy the whole thing first.
So, something like this (wholly untested):
char *copy = xstrdup(mystr);
char *p;
char **arry;
size_t count = 0;
size_t i;
for (p = copy; *p; p++)
if (*p == '\n')
count++;
arry = xmalloc((count + 1) * sizeof(char *));
i = 0;
p = copy;
arry[i] = p;
while (*p)
{
if (*p == '\n')
{
*p = '\0';
arry[i++] = p+1;
}
p++;
}
return arry; /* deallocating arry and arry[0] is
the responsibility of the caller */
In the above reactions, I see only while(){} loops, where IMHO for(){} loops are more compact.
cnicutar:
for(tok = strtok(copy, "\n");tok; tok = strtok(NULL, "\n") {
/* ... */
}
FatalError:
char *word;
for ( word = strtok(mystr, " \n");word; word = strtok(NULL, " \n") {
printf("word: %s\n", word);
}
Zack:
for (arry[i=0]=p=copy; *p ; p++)
{
if (*p == '\n')
{
*p = '\0';
arry[i++] = p+1;
}
}
[the clarity of this last example is disputable]
You can use below mentioned library. It has many other useful functions.
http://www.boost.org/doc/libs/1_48_0/libs/tokenizer/index.html
Or you can use strtok function.
line is fgets'd, and running in a while loop with counter n, d is a struct with 2 char arrays, p and q. Basically, in a few words, I want to read a line, separate it into 2 strings, one up until the first space, and the other with the rest of the line. I clean up afterwards (\n from the file becomes \'0'). The code works, but is there a more idiomatic way to do this? What errors am I running into "unknowingly"?
size_t spc = strcspn(line," ");
strncpy(d[n].p, line, spc);
d[n].p[spc+1]='\0';
size_t l = strlen(line)-spc;
strncpy(d[n].q, line+spc+1, l);
char* nl = strchr(d[n].q, '\n');
if(nl){
*nl='\0';
}
n++;
EDIT: q may contain spaces.
Thanks.
This can be done with pure pointer arithmetic only. Assuming line contains the current line:
char *p = line;
char *part1, *part2;
while (*p && *p != ' ') {
p++;
}
if (*p == ' ') {
*p++ = '\0';
part1 = strdup(line);
part2 = strdup(p);
if (!part1 || !part2) {
/* insufficient memory */
}
} else {
/* line doesn't contain a space */
}
Basically you scan the string till the first occurrence of a space, then replace the space with a null character to indicate the end of the first part (strdup needs to know where to stop), and advance the pointer by one to get the rest of the string.
To make the code look even cleaner but with the overhead of calling a function, you could use strchr() instead of the while loop:
char *p = strchr(line, ' ');
char *part1, *part2;
if (p) {
*p++ = '\0';
part1 = strdup(line);
part2 = strdup(p);
}
I would write very nearly the code you have. Some tweaks:
You're not getting anything out of strncpy here, use memcpy.
You're not getting anything out of strcspn either, use strchr.
Avoid scanning parts of the string twice.
So:
char *spc = strchr(line, ' ');
memcpy(d[n].p, line, spc - line);
d[n].p[spc - line] = '\0';
spc++;
char *end = strchr(spc, '\n');
if (end)
{
memcpy(d[n].q, spc, end - spc);
d[n].q[end - spc] = '\0';
}
else
strcpy(d[n].q, spc);
n++;
You could always use:
sscanf(line, "%s %s", d[n].p, d[n].q);
Assuming the stuff you want to put into p and q does not contain spaces, and that p and q is guaranteed to be large enough to hold the tokens including zero-termination.
The scanf function is dangerous, but very useful when used correctly.
scanf("%s %[^\n]", d[n].p, d[n].q);
The %[...] directive is like %s, but instead of matching non-whitespace, it matches the characters within the brackets – or all characters except those in the brackets, if ^ is leading.
You should check the return value to see if q was actually input; this has somewhat different behavior than your code if "rest of line" is actually empty. (Or if the line starts with whitespace.)