Sides of a Triangle (or Right Triangle) - c

float a, b, c;
printf( "Enter three nonzero values:\n" );
scanf( "%f%f%f", &a, &b, &c );
When I input a = 2, b = 2, and c = 4, why does...
if( a < ( b + c ))
{
if( b < ( a + c ))
{
if( c < ( a + b ))
{
printf( "This is a triangle." );
}
else
{
printf( "This is not a triangle." );
}
}
}
return 0;
}
...print "This is not a triangle" but...
if( a < ( b + c ))
{
if( b < ( a + c ))
{
if( c < ( a + b ))
{
printf( "This is a triangle." );
}
}
}
else
{
printf( "This is not a triangle." );
}
...does not? A solution I am looking at uses the latter code. However, the line where "This is not a triangle" should be is just blank in my command propt when I run the program.
I am using notepad++ with Developer Command Prompt for VS 2019.
vvvvvvv SOLVED vvvvvvvv
This is how I solved the exercise if anyone at the same learning stage as me is interested. I am using a book to learn c programming and I've only read three chapters. Therefore, I wanted to use only what I have learned from the first three chapters.
float a, b, c, temp, no = 0, count = 1;
printf( "Enter three nonzero values:\n" );
scanf( "%f%f%f", &a, &b, &c );
while ( count < 3 ) {
if(a + b > c){
/* Switch place of a and b */
temp = a;
a = b;
b = temp;
/* Switch place of b and c */
temp = c;
c = b;
b = temp;
count++;
}
else {
no++;
/* Switch place of a and b */
temp = a;
a = b;
b = temp;
/* Switch place of b and c */
temp = c;
c = b;
b = temp;
count++;
}
}
if ( no > 0 ) {
printf ( "This is not a valid triangle." );
}
else {
printf ( "This is a valid triangle." );
}
return 0;
This solution uses a while loop to determine if the sides of a triangle can be a valid triangle. I use variable temp to switch places of the sides and then add one to variable no if one of the combinations is not a valid triangle.
I also want to add that the solution for this exercise on chegg.com is false. It confused me a lot.
vvvvvvvv ANOTHER SOLUTION vvvvvvv
The next exercise in my book was to calculate if three values could be the sides of a right triangle. When I solved this I realized that the same code could be used for a regular triangle, too.
float a, b, largest, temp;
printf( "Enter three nonzero values:\n" );
scanf( "%f%f%f", &largest, &a , &b );
if ( a > largest ) {
temp = largest;
largest = a;
a = temp;
}
if ( b > largest ) {
temp = largest;
largest = b;
b = temp;
}
/* a + b > largest if it's a regular triangle */
if ( a * a + b * b == largest * largest ) {
printf( "This is a valid right triangle" );
}
else {
printf( "This is not a valid right triangle" );
}
return 0;
So instead of looping, just compare the variables a and b with largest to find out which variable is largest. And then use the pythagorean theorem to find out if the sides can represent a right triangle, or the a + b > c if the it is a regular triangle.
I prefer this way rather than using unnecessary looping.

Because this is false: if( c < ( a + b )) since 4 < (2 + 2) is false. Therefore the else branch will executes. In your second variant it will only print "This is not a triangle." when the first if is false otherwise not. Try this
if ( (a < ( b + c )) && (b < ( a + c )) && (c < ( a + b )) )
printf( "This is a triangle.");
else
printf( "This is not a triangle.");
Note: This would also print "This is not a triangle." since by your logic with those values it is not a triangle anyway.

You are missing a bracket
if( c < ( a + b ))
{
printf( "This is a triangle." );
}else {
printf( "This is not a triangle." );
}
If wasn't closed before else

Notice the curly brackets and indentation.
In the 1st example:
if(...)
if(...)
if( c < ( a + b ))
{
printf( "This is a triangle." );
}
else
{
printf( "This is not a triangle." );
}
In order to get to the third if statement, the previous two ifs (the first AND the second if) have to be true. Our third if statement has an else branch, which will execute if the third condition is false.
In the 2nd example:
if( a < ( b + c ))
{
// some more code
}
else
{
printf( "This is not a triangle." );
}
else branch will execute only if the first condition is false. If the first condition is true, this else will never be executed.
That being said, the first example translates to:
If a is less than b+c AND b is less than a+c AND c is less than a+b
Then this is a triangle
Else this is not a triangle
The second example translates to:
If a is less than b+c
Then check other conditions
Else this is not a triangle
As a side note, be careful when comparing float numbers

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;
}

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

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;
}

Checking whether a string consists of two repetitions

I am writing a function that returns 1 if a string consists of two repetitions, 0 otherwise.
Example: If the string is "hellohello", the function will return 1 because the string consists of the same two words "hello" and "hello".
The first test I did was to use a nested for loop but after a bit of reasoning I thought that the idea is wrong and is not the right way to solve, here is the last function I wrote.
It is not correct, even if the string consists of two repetitions, it returns 0.
Also, I know this problem could be handled differently with a while loop following another algorithm, but I was wondering if it could be done with the for as well.
My idea would be to divide the string in half and check it character by character.
This is the last function I tried:
int doubleString(char *s){
int true=1;
char strNew[50];
for(int i=0;i<strlen(s)/2;i++){
strNew[i]=s[i];
}
for(int j=strlen(s)/2;j<strlen(s);j++){
if(!(strNew[j]==s[j])){
true=0;
}
}
return true;
}
The problem in your function is with the comparison in the second loop: you are using the j variable as an index for both the second half of the given string and for the index in the copied first half of that string. However, for that copied string, you need the indexes to start from zero – so you need to subtract the s_length/2 value from j when accessing its individual characters.
Also, it is better to use the size_t type when looping through strings and comparing to the results of functions like strlen (which return that type). You can also improve your code by saving the strlen(s)/2 value, so it isn't computed on each loop. You can also dispense with your local true variable, returning 0 as soon as you find a mismatch, or 1 if the second loop completes without finding such a mismatch:
int doubleString(char* s)
{
char strNew[50] = { 0, };
size_t full_len = strlen(s);
size_t half_len = full_len / 2;
for (size_t i = 0; i < half_len; i++) {
strNew[i] = s[i];
}
for (size_t j = half_len; j < full_len; j++) {
if (strNew[j - half_len] != s[j]) { // x != y is clearer than !(x == y)
return 0;
}
}
return 1;
}
In fact, once you have appreciated why you need to subtract that "half length" from the j index of strNew, you can remove the need for that temporary copy completely and just use the modified j as an index into the original string:
int doubleString(char* s)
{
size_t full_len = strlen(s);
size_t half_len = full_len / 2;
for (size_t j = half_len; j < full_len; j++) {
if (s[j - half_len] != s[j]) { // x != y is clearer than !(x == y)
return 0;
}
}
return 1;
}
This loop
for(int j=strlen(s)/2;j<strlen(s);j++){
if(!(strNew[j]==s[j])){
true=0;
}
}
is incorrect. The index in the array strNew shall start from 0 instead of the value of the expression strlen( s ) / 2.
But in any case your approach is incorrect because at least you are using an intermediate array with the magic number 50. The user can pass to the function a string of any length.
char strNew[50];
The function can look much simpler.
For example
int doubleString( const char *s )
{
int double_string = 0;
size_t n = 0;
if ( ( double_string = *s != '\0' && ( n = strlen( s ) ) % 2 == 0 ) )
{
double_string = memcmp( s, s + n / 2, n / 2 ) == 0;
}
return double_string;
}
That is the function at first checks that the passed string is not empty and its length is an even number. If so then the function compares two halves of the string.
Here is a demonstration program.
#include <stdio.h>
#include <string.h>
int doubleString( const char *s )
{
int double_string = 0;
size_t n = 0;
if (( double_string = *s != '\0' && ( n = strlen( s ) ) % 2 == 0 ))
{
double_string = memcmp( s, s + n / 2, n / 2 ) == 0;
}
return double_string;
}
int main( void )
{
printf( "doubleString( \"\" ) = %d\n", doubleString( "" ) );
printf( "doubleString( \"HelloHello\" ) = %d\n", doubleString( "HelloHello" ) );
printf( "doubleString( \"Hello Hello\" ) = %d\n", doubleString( "Hello Hello" ) );
}
The program output is
doubleString( "" ) = 0
doubleString( "HelloHello" ) = 1
doubleString( "Hello Hello" ) = 0
Pay attention to that the function parameter should have the qualifier const because the passed string is not changed within the function. And you will be able to call the function with constant arrays without the need to defined one more function for constant character arrays.
it's better to do it with a while loop since you don't always have to iterate through all the elements of the string but since you want the for loop version here it is (C++ version):
int doubleString(string s){
int s_length = s.length();
if(s_length%2 != 0) {
return 0;
}
for (int i = 0; i < s_length/2; i++) {
if (s[i] != s[s_length/2 + i]){
return 0;
}
}
return 1;
}

Comparing substring of a character array with another character array in C

I have two characters arrays called arraypi and arraye containing numbers that I read from a file. Each have 1,000,000 characters. I need to start from the first character in arraye (In this case, 7) and search for it in arraypi. If 7 exists in arraypi then I have to search for the next substring of arraye(in this case, 71). Then search for 718, 7182 and so on until the substring does not exist in arraypi. Then I have to simply put the length of the biggest substring in a integer variable and print it.
Worth mentioning that arraypi contains a newline every 50 characters whereas arraye contains a newline every 80 although I don't think that will be problem right?
I tried thinking about a way to accomplish this but so far I haven't thought of something.
I am not absolutely sure if I got this right. I have something like this on my mind:
Assume that we have the whole arraypi is in a browser
You use the key combination ctrl+f for find
Start typing the contents of arraye letter by letter until you see the red no match
You want the number of characters you were able to type until then
If that's right, then an algorithm like the following should do the trick:
#include <stdio.h>
#define iswhitespace(X) ((X) == '\n' || (X) == ' ' || (X) == '\t')
int main( ) {
char e[1000] = "somet\n\nhing";
char pi[1000] = "some other t\nhing\t som\neth\n\ning";
int longestlen = 0;
int longestx = 0;
int pix = 0;
int ex = 0;
int piwhitespace = 0; // <-- added
int ewhitespace = 0; // <-- these
while ( pix + ex + piwhitespace < 1000 ) {
// added the following 4 lines to make it whitespace insensitive
while ( iswhitespace(e[ex + ewhitespace]) )
ewhitespace++;
while ( iswhitespace(pi[pix + ex + piwhitespace]) )
piwhitespace++;
if ( e[ex + ewhitespace] != '\0' && pi[pix + ex + piwhitespace] != '\0' && pi[pix + ex + piwhitespace] == e[ex + ewhitespace] ) {
// the following 4 lines are for obtaining correct longestx value
if ( ex == 0 ) {
pix += piwhitespace;
piwhitespace = 0;
}
ex++;
}
else {
if ( ex > longestlen ) {
longestlen = ex;
longestx = pix;
}
pix += piwhitespace + 1;
piwhitespace = 0;
// the two lines above could be replaced with
// pix++;
// and it would work just fine, the injection is unnecessary here
ex = 0;
ewhitespace = 0;
}
}
printf( "Longest sqn is %d chars long starting at %d", longestlen, longestx + 1 );
putchar( 10 );
return 0;
}
What's happening there is, the loop searches for a starting point for match first. Until it finds a match, it increments the index for the array being examined. When it finds a starting point, it then starts incrementing the index for the array containing the search term, keeping the other index constant.
Until a next mismatch, which is when a record-check is made, search term index is reset and examinee index starts getting incremented once again.
I hope this helps, somehow, hopefully more than resolving this single-time struggle.
Edit:
Changed the code to disregard white space characters.
Okay, since you apparently weren't really wanting this for arrays, but rather for two files with text inside, here's an appropriate solution to achieve that:
#include <stdio.h>
#define iswhitespace(X) ((X) == '\n' || (X) == ' ' || (X) == '\t')
int main( ) {
FILE * e;
FILE * pi;
if ( ( e = fopen( "e", "r" ) ) == NULL ) {
printf( "failure at line %d\n", __LINE__ );
return -1;
}
if ( ( pi = fopen( "pi", "r" ) ) == NULL ) {
printf( "failure at line %d\n", __LINE__ );
return -1;
}
int curre = fgetc( e );
int currpi = fgetc( pi );
int currentlength = 0;
int longestlength = 0;
int longestindex = 0;
int whitespaces = 0;
fpos_t startpoint;
if ( curre == EOF || currpi == EOF ) {
printf( "either one of the files are empty\n" );
return -1;
}
while ( 1 ) {
while ( iswhitespace( currpi ) )
currpi = fgetc( pi );
while ( iswhitespace( curre ) )
curre = fgetc( e );
if ( curre == currpi && currpi != EOF ) {
if ( currentlength == 0 && fgetpos( pi, &startpoint ) ) {
printf( "failure at line %d\n", __LINE__ );
return -1;
}
currentlength++;
curre = fgetc( e );
}
else if ( currentlength != 0 ) {
if ( currentlength > longestlength ) {
longestlength = currentlength;
longestindex = startpoint;
}
if ( curre == EOF ) {
printf( "Complete match!\n" );
break;
}
fsetpos( pi, &startpoint );
rewind( e );
curre = fgetc( e );
currentlength = 0;
}
if ( currpi == EOF )
break;
currpi = fgetc( pi );
}
printf( "Longest sequence is %d characters long starting at %d",
longestlength, longestindex );
putchar( 10 );
return 0;
}
It searches for a starting point, stores that starting point to return back to after determining the length of the current match. Determines the length of the current match, disregarding the whitespace on the way. Updates the record length if necessary, completely rewinds the search term file, partially-rewinds the examinee file back to the stored position.
Here's my e file:
somet
hing
And here is my pi file:
some other nhing som
eth
ing
And here's the output I get:
Complete match!
Longest sequence is 9 characters long starting at 20
By the way, fread and fwrite do not function humanly intuitive, as far as I remember. You can think of it like, computer uses a language that it itself understands while issuing those functions.
You can use strstr() function.Consider using it in a loop with return string as one of the argument.

adding { - } in a for loop : c programming

the program runs fine and clear, but i just wanted to ask why didnt we add { - } in the beggining and end of the for loop ? the program runs fine without adding them but when i tried to add { - } in the for loop the prgram didnt run fine, arent we suppose to add { - } in ever begging and end of every loop ? and why did the program run fine without them and didnt run fine with them ?
int c, first, last, middle, n, search, array[100];
printf("Enter number of elements\n");
scanf("%d",&n);
printf("Enter %d integers\n", n);
for ( c = 0 ; c < n ; c++ )
scanf("%d",&array[c]);
printf("Enter value to find\n");
scanf("%d",&search);
first = 0;
last = n - 1;
middle = (first+last)/2;
while( first <= last )
{
if ( array[middle] < search )
first = middle + 1;
else if ( array[middle] == search )
{
printf("%d found at location %d.\n", search, middle+1);
break;
}
else
last = middle - 1;
middle = (first + last)/2;
}
if ( first > last )
printf("Not found! %d is not present in the list.\n", search);
Without braces it takes ONE statement as its scope
like
for ( c = 0 ; c < n ; c++ )
scanf("%d",&array[c]);
Equivalent of
for ( c = 0 ; c < n ; c++ )
{
scanf("%d",&array[c]);
}
A loop executes the statement immediately after it in a loop. What is a statement? It can be:
A piece of code ended with ;.
A block of code started with { and ended with }.
Your for-loop
for ( c = 0 ; c < n ; c++ )
scanf("%d",&array[c]);
uses the first definition of statement, but you could also write it as
for ( c = 0 ; c < n ; c++ )
{
scanf("%d",&array[c]);
}
and it should work fine.
Informally: The for-loop has a one-statement body. To use multiple statements, you nest them in a block-statement.
If there is only one statement in the block the braces are optional

Resources