-1

You are interested in finding words that contain the letter 't' or 'T' in the first half of the word (including the middle letter if there is one). Specifically, if the first half of the word does contain a 't' or a 'T', your program should output a 1. If the first half does not contain the letter 't' or 'T', but the second half does, then your program should output a 2. Otherwise, if there is no 't' or 'T' in the word at all, your program's output should be -1. You may assume that the word entered does not have more than 50 letters.

 #include <stdio.h>
int main (void){
    int i=0;
    char word[51];
    int l=0;
    int half;
    char found1='T';
    char found2='t';
    
    
    scanf("%s",word);
    while (word[i]!='\0'){
        i++;
        
    }
    half=i/2;
    while(word[l]!='\0'){
         scanf("%s",word);
         l++;
        if((word[l]!=half)&&((word[l]==found1)&&(word[l]==found2))){
            printf("1");
        }
    if((word[l]!=i)&&((word[l]==found1)&&(word[l]==found2))&&(word[l]>=half)){
        printf("2");
    }
    }
    if(i%2!=0){
        printf("1");
    }else{
        printf("-1");
    }
    return 0;
}
C_luna
  • 13
  • 3
  • 3
    What's your question? – Stephen Newell Jan 24 '23 at 04:38
  • 4
    first of all post the whole program, second, ask a question – pm100 Jan 24 '23 at 04:43
  • i am sorry let me edit this – C_luna Jan 24 '23 at 04:50
  • I edited it if you can help me now! TT – C_luna Jan 24 '23 at 04:54
  • whats the question – pm100 Jan 24 '23 at 04:57
  • why are you comparing this `word[l]!=half`, `half` is a position in the string (say 5) and `word[l]` is a character in the string (say 'P') – pm100 Jan 24 '23 at 05:00
  • 1
    i want to know if the letter of the entered word falls on first half or second half of the word so i am basically trying to compare if T or t is there. – C_luna Jan 24 '23 at 05:14
  • 1
    I think the question is - why doesnt this work? It gives the wrong answer. The reason is because the code is plain wrong, especially that compare, its meaningless. – pm100 Jan 24 '23 at 05:21
  • yup thank you so can you help me with it also is the question not visible it's written right at the top. – C_luna Jan 24 '23 at 05:36
  • You are interested in finding words that contain the letter 't' or 'T' in the first half of the word (including the middle letter if there is one). Specifically, if the first half of the word does contain a 't' or a 'T', your program should output a 1. If the first half does not contain the letter 't' or 'T', but the second half does, then your program should output a 2. Otherwise, if there is no 't' or 'T' in the word at all, your program's output should be -1. You may assume that the word entered does not have more than 50 letters. sorry if it wasn't visible but this is the question. – C_luna Jan 24 '23 at 05:41
  • I suspect this would be a very interesting question without the _50 letter_ limit. I suspect it may be solvable, even with lengths > 10^38 with O(1) memory. – chux - Reinstate Monica Jan 24 '23 at 06:07
  • 1
    `scanf("%s",word);` is no safer than `gets(word);` See [Why gets() is so dangerous it should never be used!](https://stackoverflow.com/q/1694036/3422102). To use `scanf()` correctly when filling a string, you must use the *field-width* modifier to limit the number of characters to `sizeof word - 1` (`50`) to protect your array bounds. That is, e.g. `if (scanf ("%50s", word) != 1) { /* handle error */ }` – David C. Rankin Jan 24 '23 at 06:53
  • 1
    Additionally, you have special cases to consider the string `"t"` does not have either a first or second half -- what then?, and `"_t_"` (all odd lengths) which half does `'t'` reside in? – David C. Rankin Jan 24 '23 at 10:14

4 Answers4

1

Break it down as simple as possible:


Find the index of a T or t in the string.

Did you find it?

  • no, output 0 and quit

Did you find it in the first half?

  • no, output 2 and quit

Output 1 and quit.


Get input with:

char word[52];
fgets(word, sizeof(word), stdin);

Determine the length of a string with:

int n = strlen(word) - 1;  // Don’t count the '\n' at the end of the input

Remember that integer division rounds toward zero, so:

int half = (n + 1) / 2;

Anything < half is in the first half. Anything half is in the second half.

Dúthomhas
  • 8,200
  • 2
  • 17
  • 39
  • I am sorry but I am a little confused can you please try editing my code to re-explain? – C_luna Jan 24 '23 at 05:19
  • 1
    @user21070200 I won’t change your question. However, you are doing too much stuff. Get _one_ string. Find the index (an `int`) of the first `T` or `t` in it. Use some `if` statements to ask and answer the questions in the algorithm I gave you. This should honestly read about one or two lines of code for each bullet point I gave you. If you are overloaded then you have too much stuff going on. Delete all the stuff you are unsure about and start again. – Dúthomhas Jan 24 '23 at 05:22
  • @user21070200 use strchr to find t or T – pm100 Jan 24 '23 at 05:26
  • @user21070200 he is saying you need to start again. There is too much wrong with your current code, like why do you keep doing scanf in that loop – pm100 Jan 24 '23 at 05:27
  • 1
    For two things to find, use `int n = strcspn(word, "Tt")` – Dúthomhas Jan 24 '23 at 05:28
  • If using `fgets` then maybe do `int n = strlen(word); n--; word[n]='\0'; ` to discard that icky line feed character and be done with it. Since all upcoming iterations will have to look for `\0`. – Lundin Jan 24 '23 at 12:16
0

It may be instructive to consider a C program with no #include's.

int main(int argc, char *argv[])
/*
* Assume the input word is argv[1], empty word (not containing T) if
* no argument.  The result is in the return value of the main
* function, so we don't need to include stdio to print it.
*/
{
    if (argc < 2)
        return -1; // no T

    char *word = argv[1];

    int found = -1, length = 0, ch;
    while ((ch = *(unsigned char*)word++) != 0)
    {
        ++length;
        if (found < 0 && (ch == 't' || ch == 'T'))
            found = length;
    }

    if (found < 0)
        return -1; // no T

    return 2*(found -1) < length? 1: 2;
}

When testing, -1 appears as 255:

$ gcc -W -Wall -g so.c
$ ./a.out t; echo $?
1
$ ./a.out o; echo $?
255
$ ./a.out to; echo $?
1
$ ./a.out oto; echo $?
1
$ ./a.out ot; echo $?
2

However, non-ASCII characters don't work as expected. In the following, the first character of the argument is hwair, which takes four bytes in UTF-8 encoding:

$ ./a.out tooo; echo $?
2
Ale
  • 887
  • 10
  • 14
0

It is sufficient to detect 2 things:

  • Length of word.

  • Offset of first t or T.

The "word" does not need to be stored, just its end detected.
No need for a small (50) letter limit.

  #include <ctype.h>
  #include <stdio.h>

  int main() {
    unsigned long long word_length = 0;
    unsigned long long t_offset = 0;  // First letter in a word is at offset 1.
    int ch;
    
    do {
      ch = getchar();
      if (isalpha(ch)) {
        word_length++;
        if ((ch == 't' || ch == 'T') && (t_offset == 0)) {
          // Record offset of first "Tee".
          t_offset = word_length;
        }
      } else {
        // Detect end-of-word
        if (word_length > 0) {  
          const char *output = "-1";
          if (t_offset > 0) {
            if (t_offset <= (word_length+1)/2) output = "1";
            else output = "2"; 
          }
          puts(output);
          word_length = 0;
          t_offset = 0;
        }
      }
    } while (ch != EOF);
  }
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • this seems so reasonable but it's literally not working gives me multiple compilation errors and no answer. especially with isalpha. and the while at the end. – C_luna Jan 24 '23 at 13:54
  • @user21070200 "gives me multiple compilation errors" --> what were they? – chux - Reinstate Monica Jan 24 '23 at 16:33
  • The one error I cannot solve is isalpha if I try declaring it it doesn’t help even if I clear the compilation error there is no answer because it keeps suspecting isalpha(ch) like it’s expecting that something is missing in that statement. At this point I really don’t know what is wrong it’s so frustrating. After finally getting a suitable understandable answer it’s not working out. – C_luna Jan 24 '23 at 18:39
  • @user21070200 Does your code have `#include ` where `isalpha()` declared? Best to post the error message than only describe it. "getting a suitable understandable answer it’s not working out." --> best to post inputs used, output seen, output desired rather than only "not working out". – chux - Reinstate Monica Jan 24 '23 at 18:43
0

While you can do the comparisons character-by-character, C provides char *strpbrk(const char *s, const char *accept) that will provide the position in s of the first byte (character) in accept. Using "Tt" as your accept and word as s you receive a pointer to the first occurrence of 'T' or 't' in word, e.g.

#include <stdio.h>
#include <string.h>

#define MAXWORD 51

int main (void) {
  
  char word[MAXWORD], *ptr2t = NULL;  /* storage and ptr to t or T */
  size_t len = 0, pos = 0, mid = 0;   /* word len, tT pos & mid pos */
  
  fputs ("\nenter word (50 char max): ", stdout);   /* prompt */
  
  if (!fgets (word, MAXWORD, stdin)) {      /* read up  to 50 chars */
    puts ("(user canceled input)");
    return 0;
  }
  word[(len = strcspn (word, "\n"))] = 0;   /* save len, trim \n from end */
  
  if (!(ptr2t = strpbrk (word, "Tt"))) {    /* locate 't' or 'T' in word */
    puts ("-1");
    return 0;
  }
  
  if (len == 1) {   /* if length 1, no determination of half is possible */
    puts ("(length is 1, half determination not possible)");
    return 0;
  }
  
  mid = len / 2;                  /* get mid position */
  pos = ptr2t - word;             /* get postion in word */
  
#ifdef ODD_MID_IN_1ST             /* if considering mid character in odd */
  if (len & 1) {                  /* length part of 1st half, add 1 to  */
    mid += 1;                     /* mid.                               */
  }
#endif

  puts (pos < mid ? "1" : "2");   /* output 1 in 1st half, 2 otherwise. */
}

Following from my comments, you also have to handle the case where the length of the input is 1 as there can be no half determination (handle as you want), and you have to determine which half the mid-character in an odd length word belongs in. By default the mid-character belongs to the second-half. The define ODD_MID_IN_1ST will change the behavior to place the mid-character in the first-half (up to you).

Compile

With gcc you can use:

gcc -Wall -Wextra -pedantic -Wshadow -std=c11 -Ofast -o bin/tin1sthalf tin1sthalf.c

Where the options -Wall -Wextra -pedantic -Wshadow enable full warnings (for the most part) and checks whether there are shadowed variables. -std=c11 specifies the language standard as C11 and -Ofast is full optimization for gcc >= 4.6, prior to that the optimization levels were limited to O0, O1, O2 and O3. Add -Werror to treat warnings as errors (recommended). The executable output -o will be placed in the bin/ directory (change as needed).

Always compile with full-warnings enabled (every compiler provides options to enable warnings) and do not accept code until it compiles without warning (-Werror keeps you from cheating...)

Example Use/Output

Showing the various special case handling and general output of the program:

$ ./bin/tin1sthalf

enter word (50 char max): t
(lenght is 1, half determination not possible)

$ ./bin/tin1sthalf

enter word (50 char max): t_
1

$ ./bin/tin1sthalf

enter word (50 char max): _t
2

$ ./bin/tin1sthalf

enter word (50 char max): _t_
2

$ ./bin/tin1sthalf

enter word (50 char max): ___
-1

$ ./bin/tin1sthalf

enter word (50 char max): _T__
1

$ ./bin/tin1sthalf

enter word (50 char max): __t_
2

There are many, many ways to approach this problem. No one any more right than the other if they comply with the language standard or POSIX standard if applicable. The only difference is one of efficiency. As you learn to code, your focus should be on getting the code working and not worrying about micro optimizations early. Once you have your full program working, then profile it and worry about code optimizations at that point.

Let me know if you have questions.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • I tested it with some of the words cater, later and according to the exercise sheet it should give a 1 but this gives a two. why is it giving me a two and what can I do to make it give me a 1?( aside from that everything is perfect. like for honor it gives me -1 and for assortments it gives me a 2 ) – C_luna Jan 27 '23 at 09:42
  • only if I am able to make this give me a 1 for" later " as input this will be complete! – C_luna Jan 27 '23 at 09:43
  • Yes, that is because the mid character is placed in the second half by default. Add `#define ODD_MID_IN_1ST` under the includes and that will fix it by shifting the mid-character in odd length words to the 1st half. See the comments after `#ifdef ODD_MID_IN_1ST` in the current code explains that. Let me know if you have problems. – David C. Rankin Jan 27 '23 at 10:40