for loop, how to print integers/string two by two - c

This drives me crazy because it seems so easy, but I cannot figure it out.
I have a for-loop and it prints out words what I have entered. This version of for-loop prints it out this way:
"car - wheel - bike - handlebar",
instead I want to print it this way:
"car - wheel
bike - handlebar"
for(int i=0;i<numberOfWords;i++)
printf("%s - ",words[i]);
printf("\n");
EDIT: It prints out from an array. I have a function that takes in words and stores in an array. Then I want to pair two words side by side.

for(int i=0;i<numberOfWords;i++) }
printf("%s",words[i]);
if(i%2) printf("\n");
else printf(" - ");
}
printf("\n");
Explanation. Prints every word. And if i is odd (so after printing words[1] and words[3]) print a newline. Otherwise, print a - since another word will be printed on that line.
If the total number of words might not be even (of multiple of whatever number of words per line you want, since this code can be adapted for other than 2), then a specific code should be written for the last word. For example, adding
if(i==numberOfWords-1) break after the first printf, so that last loop iteration does not print any separator - nor newline.

As other answers have pointed out, some test of 'parity' of the loop counter will select between outputting a "spacer" or a "newline" after each word is printed. Some of those methods are arcane, and some of those methods will not properly handle the case of an odd number of words.
If you are going to make the effort to code this algorithm, it should be as capable as possible. The following works for "pairs", but it seems more lyrical to show it working for "triplets" of sequential words in an array. (Omitting checks for negative numbers and empty strings. Those are not a few of my favourite things.)
#include <stdio.h>
#include <string.h>
void out( char *w[], size_t n, size_t per ) {
// output sequential words (array elements) several per line.
for( size_t r = 0; r < n; r += per ) {
char *prfx = ""; // prefix separator for words...
for( size_t c = r; c < r+per && c < n; c++ ) {
printf( "%s%s", prfx, w[c] );
prfx = " - "; // subsequent words prefixed by this string
}
putchar( '\n' );
}
putchar( '\n' );
}
int approved( char *w ) { // suppress adding some words to the array
char *stop[] = { "and", "up", "are", "of" }; // "stopwords"
for( int i = 0; i < sizeof stop/sizeof stop[0]; i++ )
if( strcmp( w, stop[i] ) == 0 ) return 0;
return 1;
}
int main() {
char meat[] =
"Raindrops on roses and whiskers on kittens "
"Bright copper kettles and warm woolen mittens "
"Brown paper packages tied up with strings "
"These are a few of my favourite things";
char *words[100]; // sufficient
size_t nWords = 0;
// Break apart the meat into individual (approved) words
for( char *p = meat; (p = strtok( p, " \n") ) != NULL; p = NULL )
if( approved( p ) )
words[ nWords++ ] = p;
// out( words, nWords, 2 ); // now, output pairs
out( words, nWords, 3 ); // or output triplets
// out( words, nWords, 4 ); // or output quadruplets
return 0;
}
Raindrops - on - roses
whiskers - on - kittens
Bright - copper - kettles
warm - woolen - mittens
Brown - paper - packages
tied - with - strings
These - a - few
my - favourite - things
Slow day... Instead of multiple calls to strcmp() to approve (or not) certain words, there's this: (presumes that any word is <= 30 characters long.)
int approved( char *w ) {
char *stop = " and up a of ", buf[1+30+1=1], *p = buf+1;
while( (*p = *w) != '\0' ) p++, w++;
buf[0] = p[0] = ' '; p[1] = '\0';
return strstr( stop, buf ) == NULL;
}

It seems you mean the following
for ( int i = 0; i < numberOfWords; i++ )
{
if ( i % 2 == 0 )
{
printf( "\"%s - ", words[i] );
}
else
{
printf( "%s\"\n", words[i] );
}
}
The output will be
"car - wheel"
"bike - handlebar"

If you have an even number of words:
for (int i = 0; i < numberOfWords; i++)
printf("%s%s", words[i], i % 2 ? "\n" : " - ");
If you have an even or odd number of words:
int i = 0;
while (i < numberOfWords)
{
printf("%s", words[i]);
printf(i++ % 2 || i == numberOfWords ? "\n" : " - ");
}

My minimum working example uses command line parameters (argc, argv) to provide the test case array of strings, but the main difference to the other examples I have seen here is that this iterates over that array in steps of two.
It prints all pairs of words, and then catches and handles the single leftover array item in case the array contains an odd number of items.
int main(const int argc, const char *const argv[]) {
for (int i=0; i<argc; i+=2) {
if ((i+1)<argc) {
printf("word pair: %s - %s\n", argv[i], argv[i+1]);
} else {
printf("leftover word: %s\n", argv[i]);
}
}
return 0;
}

Related

How does a recursive code determine if palindrome work?

I have a problem question and a snippet code below. The snippet is filled already because I found out the solution but I do not understand why it is like that. Could you help me explain how the codes work?
Problem: Ten tiles each have strings of in between 1 and 4 letters on them (hardcoded in the code below). The goal of this problem is to complete the code below so it counts the number of different orders in which all of the tiles can be placed such that the string they form creates a palindrome (a word that reads the same forwards and backwards). All of main, as well as the function eval which determines if a particular ordering of the tiles forms a palindrome. You may call this function in the function go. Complete the recursive function (named go) to complete the solution.
Snippet code:
#include <stdio.h>
#include <string.h>
#define N 10
#define MAXLEN 5
int go(int perm[], int used[], int k, char tiles[N][MAXLEN]);
int eval(int perm[], char tiles[N][MAXLEN]);
char MYTILES[N][MAXLEN] = {
"at", "ta", "g", "cc", "ccac", "ca", "cc", "gag", "cga", "gc"
};
int
main(void)
{
int perm[N];
int used[N];
for (int i = 0; i < N; i++)
used[i] = 0;
int res = go(perm, used, 0, MYTILES);
printf("Number of tile orderings that create palindromes is %d\n", res);
return 0;
}
int
go(int perm[], int used[], int k, char tiles[N][MAXLEN])
{
if (k == N)
return eval(perm, tiles);
int res = 0;
for (int i = 0; i < N; i++) {
if (used[i])
continue;
used[i] = 1;
perm[k] = i;
res += go(perm, used, k + 1, tiles);
used[i] = 0;
}
return res;
}
int
eval(int perm[], char tiles[N][MAXLEN])
{
char tmp[N * MAXLEN];
int idx = 0;
for (int i = 0; i < N; i++) {
int len = strlen(tiles[perm[i]]);
for (int j = 0; j < len; j++)
tmp[idx++] = tiles[perm[i]][j];
}
tmp[idx] = '\0';
for (int i = 0; i < idx / 2; i++)
if (tmp[i] != tmp[idx - 1 - i])
return 0;
return 1;
}
Thank you. I appreciate all help!!
To understand this code, add the following line to the start of eval():
for( int j = 0; j < N; j++ ) printf( "%d ", perm[j] ); putchar('\n');
The for() loop in go() causes a recursion that is 10 levels deep, ultimately generating 10! (~3.6 million) permutations of the 10 indices from 0 to 9. In sequence, each of those permutations is used to concatenate the 'tokens' (the short ACTG variations) into a single string that is then tested for being palindromic by `eval()'
This is called a "brute force" search through the possibility space.
Below I've revised the code to be slightly more compact, adding two "printf debugging" lines (marked "/**/") that report what the program is doing. You'll need some patience if you wish to watch millions of permutations of 0 to 9 scroll by, or simply comment out that line and recompile. I also shuffled things around and made the two interesting arrays global instead of "whacking the stack" by passing them up/down the recursion. Less code is better. This program is "single purpose". The clarity gained justifies using global variables in this instance, imho.
More interesting is the additional puts() line that reports the palindromic sequences.
#include <stdio.h>
#include <string.h>
#define N 10
#define MAXLEN 5
char MYTILES[N][MAXLEN] = { "AT","TA","G","CC","CCAC","CA","CC","GAG","CGA","GC" };
int perm[N], used[N] = { 0 };
int go( int k ) {
if (k == N) {
// At extent of recursion here.
/**/ for( int j = 0; j < k; j++ ) printf( "%d ", perm[j] ); putchar('\n');
// Make a string in this sequence
char tmp[N*MAXLEN] = {0};
for( int i = 0; i < N; i++ )
strcat( tmp, MYTILES[ perm[ i ] ] );
// Test string for being palidromic
for( int l = 0, r = strlen( tmp ) - 1; l <= r; l++, r-- )
if( tmp[l] != tmp[r] )
return 0; // Not palidrome
/**/ puts( tmp );
return 1; // Is palidrome
}
// recursively generate permutations here
int res = 0;
for( int i = 0; i < N; i++ )
if( !used[i] ) {
used[i] = 1;
perm[k] = i;
res += go( k+1 );
used[i] = 0;
}
return res;
}
int main( void ) {
printf( "Palindromic tile orderings: %d\n", go( 0 ) );
return 0;
}
An immediate 'speed-up' would be to test that the first letter of the 0th string to be permuted matches the last letter of the 9th string... Don't bother concatenating if a palindrome is impossible from the get-go. Other optimisations are left as an exercise for the reader...
BTW: It's okay to make a copy of code and add your own print statements so that the program reports what it is doing when... Or, you could single-step through a debugger...
UPDATE
Having added a preliminary generation of a 10x10 matrix to 'gate' the workload of generating strings to be checked as palindromic, with the 10 OP supplied strings, it turns out that 72% of those operations were doomed to fail from the start. Of the 3.6 million "brute force" attempts, a quick reference to this pre-generated matrix prevented about 2.6 million of them.
It's worthwhile trying to make code efficient.
UPDATE #2:
Bothered that there was still a lot of 'fat' in the execution after trying to improve on the "brute force" in a simple way, I've redone some of the code.
Using a few extra global variables (the state of processing), the following now does some "preparation" in main(), then enters the recursion. In this version, once the string being assembled from fragments is over half complete (in length), it is checked from the "middle out" if it qualifies as being palindromic. If so, each appended fragment causes a re-test. If the string would never become a palindrome, the recursion 'backs-up' and tries another 'flavour' of permutation. This trims the possibility space immensely (and really speeds up the execution.)
char *Tiles[] = { "AT","TA","G","CC","CCAC","CA","CC","GAG","CGA","GC" };
const int nTiles = sizeof Tiles/sizeof Tiles[0];
int used[ nTiles ];
char buildBuf[ 1024 ], *cntrL, *cntrR; // A big buffer and 2 pointers.
int fullLen;
int cntTested, goCalls; // some counters to report iterations
uint32_t factorial( uint32_t n ) { // calc n! (max 12! to fit uint32_t)
uint32_t f = 1;
while( n ) f *= n--;
return f;
}
int hope() { // center outward testing for palindromic characteristics
int i;
for( i = 0; cntrL[ 0 - i ] == cntrR[ 0 + i ]; i++ ) ; // looping
return cntrR[ 0 + i ] == '\0';
}
int go( int k ) {
goCalls++;
if( k == nTiles ) { // at full extent of recursion here
// test string being palindromic (from ends toward middle for fun)
cntTested++;
for( int l = 0, r = fullLen - 1; l <= r; l++, r-- )
if( buildBuf[l] != buildBuf[r] )
return 0; // Not palindrome
/**/ puts( buildBuf );
return 1; // Is palindrome
}
// recursively generate permutations here
// instead of building from sequence of indices
// this builds the (global) sequence string right here
int res = 0;
char *at = buildBuf + strlen( buildBuf );
for( int i = 0; i < nTiles; i++ )
if( !used[i] ) {
strcpy( at, Tiles[ i ] );
// keep recursing until > half assembled and hope persists
if( at < cntrL || hope() ) {
used[i] = 1;
res += go( k+1 ); // go 'deeper' in the recursion
used[i] = 0;
}
}
return res;
}
int main( void ) {
for( int i = 0; i < nTiles; i++ )
fullLen += strlen( Tiles[i] );
if( fullLen % 2 == 0 ) // even count
cntrR = (cntrL = buildBuf + fullLen/2 - 1) + 1; // 24 ==> 0-11 & 12->23
else
cntrR = cntrL = buildBuf + fullLen/2; // 25 ==> 0-12 & 12->24
printf( "Palindromic tile orderings: %d\n", go( 0 ) );
printf( "Potential: %d\n", factorial( nTiles ) );
printf( "Calls to go(): %d\n", goCalls );
printf( "Actual: %d\n", cntTested );
return 0;
}
ATCCACGAGCCGCCGAGCACCTA
ATCCACGAGCCGCCGAGCACCTA
ATCCACGCCGAGAGCCGCACCTA
ATCCACGCCGAGAGCCGCACCTA
ATCACCGAGCCGCCGAGCCACTA
ATCACCGCCGAGAGCCGCCACTA
ATCACCGAGCCGCCGAGCCACTA
ATCACCGCCGAGAGCCGCCACTA
TACCACGAGCCGCCGAGCACCAT
TACCACGAGCCGCCGAGCACCAT
TACCACGCCGAGAGCCGCACCAT
TACCACGCCGAGAGCCGCACCAT
TACACCGAGCCGCCGAGCCACAT
TACACCGCCGAGAGCCGCCACAT
TACACCGAGCCGCCGAGCCACAT
TACACCGCCGAGAGCCGCCACAT
CCACATGAGCCGCCGAGTACACC
CCACATGAGCCGCCGAGTACACC
CCACATGCCGAGAGCCGTACACC
CCACATGCCGAGAGCCGTACACC
CCACTAGAGCCGCCGAGATCACC
CCACTAGAGCCGCCGAGATCACC
CCACTAGCCGAGAGCCGATCACC
CCACTAGCCGAGAGCCGATCACC
CACCATGAGCCGCCGAGTACCAC
CACCATGCCGAGAGCCGTACCAC
CACCTAGAGCCGCCGAGATCCAC
CACCTAGCCGAGAGCCGATCCAC
CACCATGAGCCGCCGAGTACCAC
CACCATGCCGAGAGCCGTACCAC
CACCTAGAGCCGCCGAGATCCAC
CACCTAGCCGAGAGCCGATCCAC
Palindromic tile orderings: 32
Potential: 3628800
Calls to go(): 96712
Actual: 32
UPDATE #3 (having fun)
When there's too much code, and an inefficient algorithm, it's easy to get lost and struggle to work out what is happening.
Below produces exactly the same results as above, but shaves a few more operations from the execution. In short, go() is called recursively until at least 1/2 of the candidate string has been built-up. At that point, hope() is asked to evaluate the string "from the middle, out." As long as the conditions of being palindromic (from the centre, outward) are being met, that evaluation is repeated as the string grows (via recursion) toward its fullest extent. It is the "bailing-out early" that makes this version far more efficient than the OP version.
One further 'refinement' is that the bottom of the recursion is found without an extra call to \0. Once one has the concepts of recursion and permutation, this should all be straight forward...
char *Tiles[] = { "AT", "TA", "G", "CC", "CCAC", "CA", "CC", "GAG", "CGA", "GC" };
const int nTiles = sizeof Tiles/sizeof Tiles[0];
int used[ nTiles ];
char out[ 1024 ], *cntrL, *cntrR;
int hope() { // center outward testing for palidromic characteristics
char *pL = cntrL, *pR = cntrR;
while( *pL == *pR ) pL--, pR++;
return *pR == '\0';
}
int go( int k ) {
int res = 0;
char *at = out + strlen( out );
for( size_t i = 0; i < nTiles; i++ )
if( !used[i] ) {
strcpy( at, Tiles[ i ] );
if( at >= cntrL && !hope() ) // abandon this string?
continue;
if( k+1 == nTiles ) { // At extent of recursion here.
puts( out );
return 1;
}
used[i] = 1, res += go( k+1 ), used[i] = 0;
}
return res;
}
int main( void ) {
int need = 0;
for( size_t i = 0; i < nTiles; i++ )
need += strlen( Tiles[ i ] );
cntrL = cntrR = out + need/2; // odd eg: 25 ==> 0-12 & 12->24
cntrL -= (need % 2 == 0 ); // but, if even eg: 24 ==> 0-11 & 12->23
printf( "Palindromic tile orderings: %d\n", go( 0 ) );
return 0;
}

How to get the length of this array without strlen(), sizeof(arr) / sizeof(arr[0]); does not work, C language

This program, tokenizes a user input string, removes extra spaces and saves each word into a 2D array and then print the tokens
EXAMPLE:
input: " Hello world string house and car"
output and EXPECTED output:
token[0]: Hello
token[1]: world
token[2]: string
token[3]: house
token[4]: and
token[5]: car
THE PROBLEM:
the problem is that I achieved this by using strlen() function when printing the tokens(code located at the very bottom), I am not supposed to use any other library than stdio.h and stdlib.h, since strlen() function is defined in string.h i tried to use sizeof(arr) / sizeof(arr[0]); but it does not work as I want, the result using sizeof is :
token[0]: Hello
token[1]: world
token[2]: string
token[3]: house
token[4]: and
token[5]: car
�oken[6]: ��
token[7]: �
token[8]: ����
token[9]: �
token[10]:
I WOULD LIKE TO HAVE THE EXPECTED OUTPUT WITHOUT USING STRLEN()
#include<stdio.h>
#include <stdlib.h>
#define TRUE 1
char tokenize(char *str, char array[10][20])
{
int n = 0, i, j = 0;
for(i = 0; TRUE; i++)//infinite loop until is the end of the string '\0'
{
if(str[i] != ' '){
//position 1, char 1
array[n][j++] = str[i];// if, it is not space, we save the character
}
else{
array[n][j++] = '\0';//end of the first word
n++;// position for next new word
j=0;// start writting char at position 0
}
if(str[i] == '\0')
break;
}
return 0;
}
//removes extra spaces
char* find_word_start(char* str){
/*also removes all extra spaces*/
char *result = (char*) malloc(sizeof(char) *1000);
int c = 0, d = 0;
// no space at beginning
while(str[c] ==' ') {
c++;
}
while(str[c] != '\0'){ // till end of sentence
result[d++] = str[c++]; //take non-space characters
if(str[c]==' ') { // take one space between words
result[d++] = str[c++];
}
while(str[c]==' ') { //
c++;
}
}
result[d-1] = '\0';
//print or return char?
return result;
free(result);
}
int main()
{
char str[]=" Hello world string dudes and dudas ";
//words, and chars in each word
char arr[10][20];
//call the method to tokenize the string
tokenize(find_word_start(str),arr);
int row = sizeof(arr) / sizeof(arr[0]);
/*----------------------------------------------------------------------*/
/*----------------------------------------------------------------------*/
for(int i = 0;i <= strlen(arr);i++)
/*----------------------------------------------------------------------*/
/*----------------------------------------------------------------------*/
printf("token[%d]: %s\n", i, arr[i]);
return 0;
}
Your code using strlen() may appear the work in this instance but it is not correct.
strlen(arr) makes no semantic sense because arr is not a string. It happens in this case to return 5 because arr has the same address as arr[0], then you kludged it to work for the 6 word output by using the test i <= strlen(arr) in the for loop. The two values strlen(arr) and the number of strings stored in arr are not related.
The expression sizeof(arr) / sizeof(arr[0]) determines the run-time constant number arrays within the array of arrays arr (i.e. 10), not the number of valid strings assigned. It is your code's responsibility to keep track of that either with a sentinel value such as an empty string, or by maintaining a count of strings assigned.
I suggest you change tokenize to return the number of strings (currently it is inexplicably defined to return a char, but in fact only ever rather uselessly returns zero):
int tokenize( char* str, char array[][20] )
{
...
return n ;
}
Then:
int rows = tokenize( find_word_start(str), arr ) ;
for( int i = 0; i < rows; i++ )
{
printf( "token[%d]: %s\n", i, arr[i] ) ;
}

My executable stops running when I try to runmy program in Eclipse CDT

After I build my project, I seem to be getting this message where it says that my program Cyber Dojo 1 has stopped working. This is shown below:
Now there are a few resources online, including:
This SO post, which has one answer that has not been accepted. The answer is not valid, as I do not have any arguments for my program.
This forum post itself on the Eclipse Community Forums. This has a few good suggestions, especially the one that relates to changing MinGW's linker flags. However, this would apply to a C++ program and not a C program. This is also a post that deals with the same problem, but once again, for C++.
And that is why I am currently looking for a solution for this problem for a C program on my Eclipse CDT.
Here is my code:
//Checking number as input
static void isNotValidCharacter1(void)
{
assert(answer('3') == NULL);
}
//Checking special character
static void isNotValidCharacter2(void)
{
assert(answer('!') == NULL);
}
//Checking lowercase letter
static void isNotValidCharacter3(void)
{
assert(answer('c') == NULL);
}
static void validCharacter(char **sample_answer)
{
int i, j;
for (i = 1; i < 11; i++) {
for (j = 1; j < 11; j++) {
assert((answer('F'))[i][j] == sample_answer[i][j]);
}
}
}
//Random Number Corner Checks Follow:
// Randomly creates a number/ character and checks the leftmost and rightmost corner characters
// as the character itself
static char psuedoRandomNumberGeneratedCharacterCheck1(void)
{
// Creating the random number between 65 and 90
int rn;
srand(time(NULL));
rn = (rand() % 25) + 65;
int distA = rn - 65;
//converting it to a character
char c_rn = (char)rn;
//checking the leftmost and rightmost corner characters
assert(answer(rn)[distA][0] == c_rn);
assert(answer(rn)[distA][distA*2] == c_rn);
return c_rn;
}
// Randomly creates a number/ characters and the checks the uppermost and lowermost corner characters
// corners as 'A'
static char psuedoRandomNumberGeneratedCharacterCheck2(void)
{
// Creating the random number between 65 and 90
int rn;
srand(time(NULL));
rn = (rand() % 25) + 65;
int distA = rn - 65;
//converting it to a character
char c_rn = (char)rn;
//checking the uppermost and lowermost corner characters
assert(answer(rn)[0][distA] == 'A');
assert(answer(rn)[distA*2][distA] == 'A');
return c_rn;
}
static void validCharacterA(void)
{
char **aDiamond = answer('A');
aDiamond[0][0] = 'A';
}
int main(void)
{
//Not valid character tests
isNotValidCharacter1();
puts("Number not accepted");
puts("special pause for debugging");
isNotValidCharacter2();
puts("Special Character not accepted");
isNotValidCharacter3();
puts("lowercase not accepted");
//Psuedorandom Tests
char prc1 = psuedoRandomNumberGeneratedCharacterCheck1();
printf("random character '%c' chosen and the leftmost and rightmost corner characters", prc1);
char prc2 = psuedoRandomNumberGeneratedCharacterCheck2();
printf("random character '%c' chosen and the leftmost and rightmost corner characters", prc2);
// Acid Test for the letter 'F'
//Square of 11 letters declared
char **Fanswer = malloc(11 * sizeof(*Fanswer));
int i;
for (i =0; i <11; i++) {
Fanswer[i] = malloc(11 * sizeof(char));
}
strcpy( Fanswer[0], " A ");
strcpy( Fanswer[1], " B B ");
strcpy( Fanswer[2], " C C ");
strcpy( Fanswer[3], " D D ");
strcpy( Fanswer[4], " E E ");
strcpy( Fanswer[5], "F F");
strcpy( Fanswer[6], " E E ");
strcpy( Fanswer[7], " D D ");
strcpy( Fanswer[8], " C C ");
strcpy( Fanswer[9], " B B ");
strcpy(Fanswer[10], " A ");
validCharacter(Fanswer);
puts("answer for F is correct");
validCharacterA();
puts("Answer for A is correct");
//All tests have passed and the end of the program
puts("All tests passed");
}
And my program for answer() is as follows:
char** answer(char c)
{
if (check(c)) {
printf("\n");
} else {
printf("Not a valid character\n");
return NULL;
}
//--------------------------------------------------------------------------------------------------------
// Preprocessing
//--------------------------------------------------------------------------------------------------------
//processing declarations
int ascii = (int)c;
int distA = ascii - 'A';
//Number of Rows and Columns
int n = ( distA * 2 ) + 1;
//Declare the column of pointers
char **diamond = malloc(n * sizeof(*diamond));
//Declare the row of characters
// 2D array declared here to save on computation in situations where characters are not valid
int i;
for (i=0; i<n; i++) {
diamond[i] = malloc(n * sizeof(char));
}
//--------------------------------------------------------------------------------------------------
// Processing
//--------------------------------------------------------------------------------------------------
//Fill in the Array
if (n == 1) {
diamond[0][0] = c;
} else {
diamond[distA][0] = c;
diamond[distA][distA*2] = c;
for (i = 1; i <= distA; i++) {
diamond[distA-i][i] = (char)(ascii - i);
diamond[distA-i][(distA*2)-i] = (char)(ascii - i);
diamond[distA+i][i] = (char)(ascii - i);
diamond[distA+i][(distA*2)-i] = (char)(ascii - i);
}
}
//-------------------------------------------------------------------------------------------------
// Postprocessing
//---------------------------------------------------------------------------
return diamond;
}
If you are a beginer with Eclipse and you don't know how to use a debugger, you can look some tutorial.
https://www.youtube.com/watch?v=azInZkPP56Q
But even after this tutorial you have difficulty to making your debuger works (because sometimes it depends how installed your Eclipse, your compiler and other things), you can try to put a big part of your code in comment and see if the problem is gone. And little by little reduce the amount of code you put in comment. When the bug reapear it means it's somewhere inside the part you removed the comment recently.
The last method is not the best way to debug your program but can be usefull for beginners and give you another alternative if you have difficulty to use your debugger.

How to reverse a sentence in C and Perl

If the sentence is
"My name is Jack"
then the output should be
"Jack is name My".
I did a program using strtok() to separate the words and then push them onto a stack,
popping them and concatenating.
Is there any other, more efficient way than this?
Is it easier to do in Perl?
Whether it is more efficient or not will be something you can test but in Perl you could do something along the lines of:
my $reversed = join( " ", reverse( split( / /, $string ) ) );
Perl makes this kind of text manipulation very easy, you can even test this easily on the shell:
echo "run as fast as you can" | perl -lne 'print join $",reverse split /\W+/'
or:
echo "all your bases are belong to us" | perl -lne '#a=reverse /\w+/g;print "#a"'
The strategy for C could be this:
1) Reverse the characters of the string. This results in the words being the right general position, albeit backward.
2) Reverse the characters of each word in the string.
We will need one function to reverse characters in a buffer:
/*
* Reverse characters in a buffer.
*
* If provided "My name is Jack", modifies the input to become
* "kcaJ si eman yM".
*/
void reverse_chars(char * buf, int cch_len)
{
char * front = buf, *back = buf + cch_len - 1;
while (front < back)
{
char tmp = *front;
*front = *back;
*back = tmp;
front ++;
back --;
}
}
For the purpose of breaking the input buffer into words, a function which returns the number of non-space characters in the buffer. (strtok() modifies the buffer and is harder to use in-place)
int word_len(char *input)
{
char * p = input;
while (*p && !isspace(*p))
p++;
return p - input;
}
Finally, we will need a function which uses those two helpers to achieve the strategy described in the first paragraph.
/*
* Reverse words in a buffer.
*
* Given the input "My name is Jack", modifies the input to become
* "Jack is name My"
*/
void reverse_words(char *input)
{
int cch_len = strlen(input);
/* Part 1: Reverse the string characters. */
reverse_chars(input, cch_len);
char * p = input;
/* Part 2: Loop over one word at a time. */
while (*p)
{
/* Skip leading spaces */
while (*p && isspace(*p))
p++;
if (*p)
{
/* Advance one complete word. */
int cch_word = word_len(p);
reverse_chars(p, cch_word);
p += cch_word;
}
}
}
You've gotten a couple of versions in C, but they strike me as a bit more verbose than is probably really necessary. Absent a reason to do otherwise, I'd consider something like this:
#define MAX 32
char *words[MAX];
char word[256];
int pos = 0;
for (pos=0; pos<MAX && scanf("%255s", word); pos++)
words[pos] = strdup(word);
while (--pos >= 0)
printf("%s ", words[pos]);
One possible "intermediate" level between C and Perl would be C++:
std::istringstream input("My name is Jack");
std::vector<std::string> words((std::istream_iterator<std::string>(input)),
std::istream_iterator<std::string>());
std::copy(words.rbegin(), words.rend(),
std::ostream_iterator<std::string>(std::cout, " "));
Here is a C idea that uses a little recursion to do the stacking for you:
void rev(char * x){
char * p;
if(p = strchr(x, ' ')){
rev(p+1);
printf("%.*s ", p-x, x);
}
else{
printf("%s ", x);
}
}
Some fun with a little help from regexp and perl special variables :)
$_ = "My name is Jack";
unshift #_, "$1 " while /(\w+)/g;
print #_;
EDIT
And a killer (by now):
$,=' ';print reverse /\w+/g;
Little explanation: $, is special variable for print output separator. Of course you can do it in shorter way without this special var:
print reverse /\w+ ?/g;
but the result might be not as satisfactiry as example above.
Using reverse:
my #words = split / /, $sentence;
my $newSentence = join(' ', reverse #words);
It's probably a lot easier to do in Perl, but...
char *strrtok(char *str, const char *delim)
{
int i, j;
for (i = strlen(str) - 1; i > 0; i--)
{
// Sets the furthest set of contiguous delimiters to null characters
if (strchr(delim, str[i]))
{
j = i + 1;
while (strchr(delim, str[i]) && i >= 0)
{
str[i] = '\0';
i--;
}
return &(str[j]);
}
}
return str;
}
This should work similarly to strtok() in reverse, but you continue to pass the pointer to the original string location rather than passing NULL after the first call. Also, you should get empty strings for start and end cases.
C version:
#include <string.h>
int main()
{
char s[] = "My name is Jack";
char t[100];
int i = 0, j = 0, k = 0;
for(i = strlen(s) - 1 ; i >= 0 ;i--)
{
if(s[i] == ' ' || i == 0)
{
j = i == 0 ? i : i + 1;
for(j = j; s[j] != '\0'; j++) t[k++] = s[j];
t[k++] = ' ';
s[i] = '\0';
}
}
t[k] = '\0';
printf("%s\n", t);
return 0;
}
C example
char * srtrev (char * str) {
int l = strlen(str);
char * rev;
while(l != 0)
{
rev += str[ --l];
}
return rev;
}

Finding unique elements in an string array in C

C bothers me with its handling of strings. I have a pseudocode like this in my mind:
char *data[20];
char *tmp; int i,j;
for(i=0;i<20;i++) {
tmp = data[i];
for(j=1;j<20;j++)
{
if(strcmp(tmp,data[j]))
//then except the uniqueness, store them in elsewhere
}
}
But when i coded this the results were bad.(I handled all the memory stuff,little things etc.) The problem is in the second loop obviously :D. But i cannot think any solution. How do i find unique strings in an array.
Example input : abc def abe abc def deg entered
unique ones : abc def abe deg should be found.
You could use qsort to force the duplicates next to each other. Once sorted, you only need to compare adjacent entries to find duplicates. The result is O(N log N) rather than (I think) O(N^2).
Here is the 15 minute lunchtime version with no error checking:
typedef struct {
int origpos;
char *value;
} SORT;
int qcmp(const void *x, const void *y) {
int res = strcmp( ((SORT*)x)->value, ((SORT*)y)->value );
if ( res != 0 )
return res;
else
// they are equal - use original position as tie breaker
return ( ((SORT*)x)->origpos - ((SORT*)y)->origpos );
}
int main( int argc, char* argv[] )
{
SORT *sorted;
char **orig;
int i;
int num = argc - 1;
orig = malloc( sizeof( char* ) * ( num ));
sorted = malloc( sizeof( SORT ) * ( num ));
for ( i = 0; i < num; i++ ) {
orig[i] = argv[i + 1];
sorted[i].value = argv[i + 1];
sorted[i].origpos = i;
}
qsort( sorted, num, sizeof( SORT ), qcmp );
// remove the dups (sorting left relative position same for dups)
for ( i = 0; i < num - 1; i++ ) {
if ( !strcmp( sorted[i].value, sorted[i+1].value ))
// clear the duplicate entry however you see fit
orig[sorted[i+1].origpos] = NULL; // or free it if dynamic mem
}
// print them without dups in original order
for ( i = 0; i < num; i++ )
if ( orig[i] )
printf( "%s ", orig[i] );
free( orig );
free( sorted );
}
char *data[20];
int i, j, n, unique[20];
n = 0;
for (i = 0; i < 20; ++i)
{
for (j = 0; j < n; ++j)
{
if (!strcmp(data[i], data[unique[j]]))
break;
}
if (j == n)
unique[n++] = i;
}
The indexes of the first occurrence of each unique string should be in unique[0..n-1] if I did that right.
Why are you starting second loop from 1?
You should start it from
i+1. i.e.
for(j=i+1;j<20;j++)
Like if the list is
abc
def
abc
abc
lop
then
when i==4
tmp="lop"
but then the second loop starts which is from 1 to 19. This means it will get a value of 4 too at one stage, and then
data[4], which is "lop", will be same as tmp. So although "lop" is unique but it will be flagged as repeated.
Hope it was helpful.
Think a bit more about your problem -- what you really want to do is look at the PREVIOUS strings to see if you've already seen it. So, for each string n, compare it to strings 0 through n-1.
print element 0 (it is unique)
for i = 1 to n
unique = 1
for j = 0 to i-1 (compare this element to the ones preceding it)
if element[i] == element[j]
unique = 0
break from loop
if unique, print element i
Might it be that your test is if (strcmp (this, that)) which will succeed if the two are different? !strcmp is probably what you want there.

Resources