I'm reading a file in my C program and comparing every word in it with my word, which is entered via command line argument. But I get crashes, and I can't understand what's wrong. How do I track such errors? What is wrong in my case?
My compiler is clang. The code compiles fine. When running it says 'segmentation fault'.
Here is the code.
#include <stdio.h>
#include <string.h>
int main(int argc, char* argv[])
{
char* temp = argv[1];
char* word = strcat(temp, "\n");
char* c = "abc";
FILE *input = fopen("/usr/share/dict/words", "r");
while (strcmp(word, c))
{
char* duh = fgets(c, 20, input);
printf("%s", duh);
}
if (!strcmp (word, c))
{
printf("FOUND IT!\n");
printf("%s\n%s", word, c);
}
fclose(input);
}
The issue here is that you are trying to treat strings in C as you might in another language (like C++ or Java), in which they are resizable vectors that you can easily append or read an arbitrary amount of data into.
C strings are much lower level. They are simply an array of characters (or a pointer to such an array; arrays can be treated like pointers to their first element in C anyhow), and the string is treated as all of the characters within that array up to the first null character. These arrays are fixed size; if you want a string of an arbitrary size, you need to allocate it yourself using malloc(), or allocate it on the stack with the size that you would like.
One thing here that is a little confusing is you are using a non-standard type string. Given the context, I'm assuming that's coming from your cs50.h, and is just a typedef to char *. It will probably reduce confusion if you actually use char * instead of string; using a typedef obscures what's really going on.
Let's start with the first problem.
string word = strcat(argv[1], "\n");
strcat() appends the second string onto the first; it starts from the null terminator of the first string, and replaces that with the first character of the second string, and so on, until it reaches a null in the second string. In order for this to work, the buffer containing the first string needs to have enough room to fit the second one. If it does not, you may overwrite arbitrary other memory, which could cause your program to crash or have all kinds of other unexpected behavior.
Here's an illustration. Let's say that argv[1] contains the word hello, and the buffer has exactly as much space as it needs for this. After it is some other data; I've filled in other for the sake of example, though it won't actually be that, it could be anything, and it may or may not be important:
+---+---+---+---+---+---+---+---+---+---+---+---+
| h | e | l | l | o | \0| o | t | h | e | r | \0|
+---+---+---+---+---+---+---+---+---+---+---+---+
Now if you use strcat() to append "\n", you will get:
+---+---+---+---+---+---+---+---+---+---+---+---+
| h | e | l | l | o | \n| \0| t | h | e | r | \0|
+---+---+---+---+---+---+---+---+---+---+---+---+
You can see that we've overwritten the other data that was after hello. This may cause all kinds of problems. To fix this, you need to copy your argv[1] into a new string, that has enough room for it plus one more character (and don't forget the trailing null). You can call strlen() to get the length of the string, then add 1 for the \n, and one for the trailing null, to get the length that you need.
Actually, instead of trying to add a \n to the word you get in from the command line, I would recommend stripping off the \n from your input words, or using strncmp() to compare all but the last character (the \n). In general, it's best in C to avoid appending strings, as appending strings means you need to allocate memory and copy things around, and it can be easy to make mistakes doing so, as well as being inefficient. Higher level languages usually take care of the details for you, making it easier to append strings, though still just as inefficient.
After your edit, you changed this to:
char* temp = argv[1];
char* word = strcat(temp, "\n");
However, this has the same problem. A char * is a pointer to a character array. Your temp variable is just copying the pointer, not the actual value; it is still pointing to the same buffer. Here's an illustration; I'm making up addresses for the purposes of demonstration, in the real machine there will be more objects in between these things, but this should suffice for the purpose of demonstration.
+------------+---------+-------+
| name | address | value |
+------------+---------+-------+
| argv | 1000 | 1004 |-------+
| argv[0] | 1004 | 1008 | --+ <-+
| argv[1] | 1006 | 1016 | --|---+
| argv[0][0] | 1008 | 'm' | <-+ |
| argv[0][1] | 1009 | 'y' | |
| argv[0][2] | 1010 | 'p' | |
| argv[0][3] | 1011 | 'r' | |
| argv[0][4] | 1012 | 'o' | |
| argv[0][5] | 1013 | 'g' | |
| argv[0][6] | 1014 | 0 | |
| argv[1][0] | 1016 | 'w' | <-+ <-+
| argv[1][1] | 1017 | 'o' | |
| argv[1][2] | 1018 | 'r' | |
| argv[1][3] | 1019 | 'd' | |
| argv[1][4] | 1020 | 0 | |
+------------+---------+-------+ |
Now when you create your temp variable, all you are doing is copying argv[1] into a new char *:
+------------+---------+-------+ |
| name | address | value | |
+------------+---------+-------+ |
| temp | 1024 | 1016 | --+
+------------+---------+-------+
As a side note, you also shouldn't ever try to access argv[1] without checking that argc is greater than 1. If someone doesn't pass any arguments in, then argv[1] itself is invalid to access.
I'll move on to the next problem.
string c = "abc";
// ...
char* duh = fgets(c, 20, input);
Here, you are referring to the static string "abc". A string that appears literally in the source, like "abc", goes into a special, read-only part of the memory of the program. Remember what I said; string here is just a way of saying char *. So c is actually just a pointer into this read-only section of memory; and it has only enough room to store the characters that you provided in the text (4, for abc and the null character terminating the string). fgets() takes as its first argument a place to store the string that it is reading, and its second the amount of space that it has. So you are trying to read up to 20 bytes, into a read-only buffer that only has room for 4.
You need to either allocate space for reading on the stack, using, for example:
char c[20];
Or dynamically, using malloc():
char *c = malloc(20);
First problem I see is this:
string word = strcat(argv[1], "\n");
You are adding characters to the end of a buffer here.
A buffer allocated for you by the runtime enviroment, that you should consider read only.
EDIT
I'm afraid your change to the code still has the same effect.
char* temp = argv[1];
Has temp pointing to the same buffer as argv[1].
You need to allocate a buffer the proper size, and use it.
char* temp = (char*)malloc(sizeof(char) * (strlen(argv[1]) + 2));
The +2 is for the adding \n and \0 at the end.
Than you do this:
strcpy(temp, argv[1]);
strcat(temp,"\n");
The code is rather flawed. Another one:
char* duh = fgets(c, 20, input);
Here you define a pointer to char, do not initialize it (hence it contains a random value) and then you write up to 20 bytes to the address pointed to by the random data. If you're lucky you just get a cash. If not, you overwrite some other important data. Fortunately most of the systems in use today won't let you access address space of another program, so the code wreaks havoc only on itself.
The line in question could look like:
#define BUFFERSIZE 1024
...
while (reasonable condition) {
char *duh = malloc(BUFERSIZE);
if (NULL == duh) { /* not enough memory - handle error, and exit */
}
duh = fgets(duh, BUFFERSIZE, input);
if (NULL == duh) { /* handle error or EOF condition */
} else { /* check that the line is read completely,
i.e. including end-of-line mark,
then do your stuff with the data */
}
free (duh);
}
Of course, you can allocate the buffer only once (outside of the loop) and reuse it. The #define makes it easy to adjust the maximum buffer size.
Alternatively, on recent systems, you can use getline(), which is able to allocate a buffer of appropriate size for you. That you must free() at the end of the loop.
If you are on Linux/BSD, use man (e.g. man fgets) to get information on the functions, otherwise resort to internet or a decent book on C for documentation.
First, My C knowledge is old, so I'm not sure what a string is. Either way, it's helpful, but not absolutely required to have a nice pre-zeroed buffer in which to read contents of the file. So whether you zero word or do something like the following, zero the input first.
#define IN_BUF_LEN 120
char in_buf[IN_BUF_LEN] = {0};
120 characters is a safe size, assuming most of your text lines are around 80 characters or less long.
Second, you're basing your loop of the value of a strcmp rather than actually reading the file. It might accomplish the same thing, but I'd base my while on reaching end of file.
Finally, you've declared duh a pointer, not a place to store what fgets returns. That's a problem, too. So, duh should be declared similarly to in_buf above.
Finally, you're assigning the value of argv[1] at compile time, not run-time. I can't see where that's getting you what you want. If you declare temp as a pointer and then assign argv[1] to it, you'll just have another pointer to argv[1], but not actually have copied the value of argv[1] to a local variable. Why not just use argv[1]?
Related
I wanted to copy string with the following code and it didn't copy the '\0'.
void copyString(char *to, char *from)
{
do{
*to++ = *from++;
}while(*from);
}
int main(void)
{
char to[50];
char from[] = "text2copy";
copyString(to, from);
printf("%s", to);
}
This is output to the code:
text2copyÇ■ ║kvu¡lvu
And every time I rerun the code the code, the character after text2copy changes, so while(*from) works fine but something random is copied instead of '\0'.
text2copyÖ■ ║kvu¡lvu
text2copy╨■ ║kvu¡lvu
text2copy╡■ ║kvu¡lvu
//etc
Why is this happenning?
The problem is that you never copy the '\0' character at the end of the string. To see why consider this:
The string passed in is a constant string sized exactly to fit the data:
char from[] = "text2copy";
It looks like this in memory:
----+----+----+----+----+----+----+----+----+----+----+----
other memory | t | e | x | t | 2 | c | o | p | y | \0 | other memory
----+----+----+----+----+----+----+----+----+----+----+----
^
from
Now let's imagine that you have done the loop several times already and you are at the top of the loop and from is pointing to the 'y' character in text2copy:
----+----+----+----+----+----+----+----+----+----+----+----
other memory | t | e | x | t | 2 | c | o | p | y | \0 | other memory
----+----+----+----+----+----+----+----+----+----+----+----
^
from
The computer executes *to++ = *from++; which copies the 'y' character to to and then increments both to and from. Now the memory looks like this:
----+----+----+----+----+----+----+----+----+----+----+----
other memory | t | e | x | t | 2 | c | o | p | y | \0 | other memory
----+----+----+----+----+----+----+----+----+----+----+----
^
from
The computer executes } while(*from); and realizes that *from is false because it points to the '\0' character at the end of the string so the loop ends and the '\0' character is never copied.
Now you might think this would fix it:
void copyString(char *to, char *from)
{
do{
*to++ = *from++;
} while(*from);
*to = *from; // copy the \0 character
}
And it does copy the '\0' character but there are still problems. The code even more fundamentally flawed because, as #JonathanLeffler said in the comments, for the empty string you peek at the contents of memory that is after the end of the string and because it was not allocated to you accessing it causes undefined behaviour:
----+----+----
other memory | \0 | other memory
----+----+----
^
from
The computer executes *to++ = *from++; which copies the '\0' character to to and then increments both to and from which makes from point to memory you don't own:
----+----+----
other memory | \0 | other memory
----+----+----
^
from
Now the computer executes }while(*from); and accesses memory that isn't yours. You can point from anywhere with no problem, but dereferencing from when it points to memory that isn't yours is undefined behaviour.
The example I made in the comments suggests saving the value copied into a temporary variable:
void copyString(char *to, char *from)
{
int test;
do{
test = (*to++ = *from++); // save the value copied
} while(test);
}
The reason I suggested that particular way was to show you that the problem was WHAT you were testing and not about testing the loop condition afterwards. If you save the value copied and then test that saved value later the character gets copied before it is tested (so the \0 gets copied) and you don't read from the incremented pointer (so there is no undefined behaviour)
But the example #JonathanLeffler had in his comments is shorter, easier to understand, and more idiomatic. It exact does the same thing without declaring a named temporary variable:
void copyString(char *to, char *from)
{
while ((*to++ = *from++) != '\0')
;
}
The code first copies the character and then tests the value that was copied (so the '\0' will be copied) but the incremented pointer is never dereferenced (so there is no undefined behaviour).
the posted code stops looping when it encounters the NUL byte, rather than afterwards.
Regarding:
}while(*from);
Suggest following that line with:
*to = '\0';
I try to understand buffer overflows. This is my code:
#include <stdio.h>
int main()
{
char buf[5] = { 0 };
char x = 'u';
printf("Please enter your name: ");
gets(buf);
printf("Hello %s!", buf);
return 0;
}
The buf array is of size five and initialized with 0es. So (with null termination) I have space for four characters. If I enter five characters (stack for example), I overwrite the null termination character and printf should print "Hello stacku!" because of the succeeding variable x. But this isn't the case. It simply prints "stack". Could someone please explain why?
The short explanation is, just because you declared 'x' on the source line after 'buf', that doesn't mean the compiler put them next to each other on the stack. With the code shown, 'x' isn't used at all, so it probably didn't get put anywhere. Even if you did use 'x' somehow (and it would have to be a way that prevents it being stuffed into a register), there's a good chance the compiler will sort it below 'buf' precisely so that it does not get overwritten by code overflowing 'buf'.
You can force this program to overwrite 'x' with a struct construct, e.g.
#include <stdio.h>
int main()
{
struct {
char buf[5];
char x[2];
} S = { { 0 }, { 'u' } };
printf("Please enter your name: ");
gets(S.buf);
printf("Hello %s!\n", S.buf);
printf("S.x[0] = %02x\n", S.x[0]);
return 0;
}
because the fields of a struct are always laid out in memory in the order they appear in the source code.1 In principle there could be padding between S.buf and S.x, but char must have an alignment requirement of 1, so the ABI probably doesn't require that.
But even if you do that, it won't print 'Hello stacku!', because gets always writes a terminating NUL. Watch:
$ ./a.out
Please enter your name: stac
Hello stac!
S.x[0] = 75
$ ./a.out
Please enter your name: stack
Hello stack!
S.x[0] = 00
$ ./a.out
Please enter your name: stacks
Hello stacks!
S.x[0] = 73
See how it always prints the thing you typed, but x[0] does get overwritten, first with a NUL, and then with an 's'?
(Have you already read Smashing the Stack for Fun and Profit? You should.)
1 Footnote for pedants: if bit-fields are involved, the order of fields in memory becomes partially implementation-defined. But that's not important for purposes of this question.
As the other answer pointed out, it's not at all guaranteed that x will sit immediately after buf in memory. But even if it did: gets is going to overwrite it. Remember: gets has no way of knowing how big the destination buffer is. (That's its fatal flaw.) It always writes the entire string it reads, plus the terminating \0. So if x happens to sit immediately after buf, then if you type a five-character string, printf is likely to print it correctly (as you saw), and if you were to inspect x's value afterwards:
printf("x = %d = %c\n", x, x);
it would likely show you that x was 0 now, not 'U'.
Here's how the memory might look initially:
+---+---+---+---+---+
buf: | | | | | |
+---+---+---+---+---+
+---+
x: | U |
+---+
So after you type "stack", it looks like this:
+---+---+---+---+---+
buf: | s | t | a | c | k |
+---+---+---+---+---+
+---+
x: |\0 |
+---+
And if you were to type "elephant" it would look like this:
+---+---+---+---+---+
buf: | e | l | e | p | h |
+---+---+---+---+---+
+---+
x: | a | n t \0
+---+
Needless to say, those three characters n, t, and \0 are likely to cause even more problems.
This is why people say not to use gets, ever. It cannot be used safely.
Local variables are generally created on the stack. In most implementations, stacks grow downward, not upward, as memory is allocated. So, it is likely that buf is at a higher address than x. That's why, when buf overflows, it does not overwrite x.
You might be able to confirm this by writing buf[-1]='v';printf("%c\n",x); although that might be affected by padding. It may also be instructive to compare the addresses with printf("%i\n",buf - &x); -- if the result is positive, then buf is at a higher address than x.
But this is all highly implementation dependent, and can change based on various compiler options. As others have said, you shouldn't rely on any of this.
#include <stdio.h>
#include <string.h>
int main()
{
int i;
char a[10];
for(i=0;i<10;i++)
{
scanf("%s",a);// >how this line is working in memory.
}
return 0;
}
In the above code, I would like to know how the string is saved in memory, since I have initialised it as a 1D character array, but does the array work as a list of strings, or a single string? Why?
In C, a string is a sequence of character values terminated by a 0-valued character - IOW, the string "Hello" is represented as the character sequence 'H', 'e', 'l', 'l', 'o', 0. Strings are stored in arrays of char (or wchar_t for wide strings):
char str[] = "Hello";
In memory, str would look something like this:
+---+
str: |'H'| str[0]
+---+
|'e'| str[1]
+---+
|'l'| str[2]
+---+
|'l'| str[3]
+---+
|'o'| str[4]
+---+
| 0 | str[5]
+---+
It is possible to store multiple strings in a single 1D array, although almost nobody does this:
char strs[] = "foo\0bar";
In memory:
+---+
strs: |'f'| strs[0]
+---+
|'o'| strs[1]
+---+
|'o'| strs[2]
+---+
| 0 | strs[3]
+---+
|'b'| strs[4]
+---+
|'a'| strs[5]
+---+
|'r'| strs[6]
+---+
| 0 | strs[7]
+---+
The string "foo" is stored starting at strs[0], while the string "bar" is stored starting at strs[4].
Normally, to store an array of strings, you'd either use a 2D array of char:
char strs[][MAX_STR_LEN] = { "foo", "bar", "bletch" };
or a 1D array of pointers to char:
char *strs[] = { "foo", "bar", "bletch" };
In the first case, the contents of the string are stored within the strs array:
+---+---+---+---+---+---+---+
strs: |'f'|'o'|'o'| 0 | ? | ? | ? |
+---+---+---+---+---+---+---+
|'b'|'a'|'r'| 0 | ? | ? | ? |
+---+---+---+---+---+---+---+
|'b'|'l'|'e'|'t'|'c'|'h'| 0 |
+---+---+---+---+---+---+---+
In the second, each strs[i] points to a different, 1D array of char:
+---+ +---+---+---+---+
strs: | | strs[0] ------> |'f'|'o'|'o'| 0 |
+---+ +---+---+---+---+
| | strs[1] ----+
+---+ | +---+---+---+---+
| | strs[2] -+ +-> |'b'|'a'|'r'| 0 |
+---+ | +---+---+---+---+
|
| +---+---+---+---+---+---+---+
+----> |'b'|'l'|'e'|'t'|'c'|'h'| 0 |
+---+---+---+---+---+---+---+
In your code, a can (and is usually intended to) store a single string that's 9 characters long (not counting the 0 terminator). Like I said, almost nobody stores multiple strings in a single 1D array, but it is possible (in this case, a can store 2 4-character strings).
char a[10];
You've allocated 10 bytes of the stack for a. But right now, it contains garbage because you never gave it a value.
Scanf doesn't know any of this. All it does is copy bytes from the standard input into a, ignorant of its size.
And why are you doing a loop 10 times? You will overwrite a each loop iteration, so you'll only have the value from the final time.
A string is per definition a null-terminated character array. So every character array becomes a string as soon as it contains a \0 somewhere, defining the end of that string.
In memory the string is just a bunch of bytes laying (for simplicity but not necessarily) in sequence. Take the string "Hello" for example
+---+---+---+---+---+---+
| H | e | l | l | o | \0|
+---+---+---+---+---+---+
Your array char a[10] is pointing to the beginning of such a memory location ('H' in the example) with enough space to store 10 characters.
By using scanf you are storing an string (character sequence + terminating \0) in that buffer (over and over again). scanf stores the characters in there and adds a terminating \0 to the element after the last one written to. This allows you to safely store any character sequence that is at most 9 characters long, since the 10th character needs to be the \0
Does a 1D array work as a list of strings, or a single string?
quite broad question.
char a[10]; declared table a which has a size of 10 the char elements
char *a[10]; declared table a which has a size of 10 char * elements which can possible point to the string (when you allocate memory for it and copy the valid C string)
In your code:
'scanf("%s",a);' a means the address of the first element of the array. So scanf writes data there, every time overwriting the previous content. If your scanf-ed input will need more 10 elements (including trailing 0) to be stored, you will get an UB and very possible SEGFAUT
You are over-writing same buffer in loop 10 times, which means buffer will contain data entered in last reading and previous 9 strings will be lost.
Also entering more than 9 characters would cause buffer overflow which would invoke undefined behavior.
You should limit number of characters scanned from input buffer and then clear the rest of the buffer. (Not fflush(stdin);)
scanf("%9s",a);
Does a 1D array work as a list of strings, or a single string?
If its terminated with null character then yes, its string, like this. And a is the address of first element.
+---+---+---+---+---+---+----+
| S | t | r | i | n | g | \0 |
+---+---+---+---+---+---+----+
a a+1 a+2
And if you pass this array ie. to printf(), he will print all characters until he reach \0.
If you would like to read list of strings, you have to declare 2D array or pointer-to-pointer-to-char and allocate enough memory for pointers.
int c;
char a[10][10];
for(i=0;i<10;i++)
{
scanf("%9s",a[i]);
while ((c = getchar()) != '\n' && c != EOF) ;
}
I'm trying to compare a string with another string and if they match I want the text "That is correct" to output but I can't seem to get it working.
Here is the code:
int main ()
{
char * password = "Torroc";
char * userInput;
printf("Please enter your password: ");
scanf("%s", userInput);
if (strcmp(password, userInput) == 0) {
printf("That is correct!");
}
}
In your code, userInput pointer does not have provision to hold the string that you are about to pass using the scanf call. You need to allocate space for the cstring userInput in your stack, before you try to save/assign any string to it. So...
You need to change the following code:
char * userInput;
to:
char userInput[200];
Here, 200 is just an arbitrary value. In your case, please select the max. length of the string + 1 for the (\0).
When you enter characters you need to store the characters somewhere.
char* userInput;
is an uninitialized pointer.
So first you declare an array for your input
char userInput[128];
Now when reading from the keyboard you need to make sure the user does not enter more characters than 127 + one for \0 because it would overwrite the stack so best way to read from the keyboard is to use fgets, it also good to check the return value, if the user simply pressed ENTER without writing anything fgets returns NULL.
if (fgets(userInput, sizeof(userInput), stdin) != NULL) {
Now you have the string that the user entered plus the end of line character. To remove it you can do something like
char* p = strchr(userInput,'\n');
if ( p != NULL ) *p = '\0';
Now you can compare the strings
if (strcmp(password, userInput) == 0) {
puts("That is correct!");
}
When you think about "a string" in C, you should see it as an array of char's.
Let me use the identifier s instead of userInput for brevity:
0 1 2 3 4 5 9
+---+---+---+---+---+---+-- --+---+
s -> | p | i | p | p | o | \0| ... | |
+---+---+---+---+---+---+-- --+---+
is what
char s[10] = "pippo";
would create.
In other words, it's a block of memory where the first 6 bytes have been initialized as shown. There is no s variable anywhere.
Instead, declaring a char * like in
char *s;
would create a variable that can hold a pointer to char:
+------------+
s| 0xCF024408 | <-- represent an address
+------------+
If you think this way, you notice immediately that doing:
scanf("%s",s);
only make sense in the first case, where there is (hopefully) enough memory to hold the string.
In the second case, the variable s points to some random address and you will end up writing something into an unknown memory area.
For completeness, in cases like:
char *s = "pippo";
you have the following situation in memory:
0 1 2 3 4 5
+---+---+---+---+---+---+ Somewhere in the
0x0B320080 | p | i | p | p | o | \0| <-- readonly portion
+---+---+---+---+---+---+ of memory
+------------+ a variable pointing
s| 0x0B320080 | <-- to the address where
+------------+ the string is
You can make s pointing somewhere else but you can't change the content of the string pointed by s.
I wanted to allocate a string array dynamically , the program is supposed to ask the user for characters and collect them in the first string in the array till letter 'q' is entered then the program starts adding the characters to the second line and so on.
When I print the characters memory location it seems like each character takes two memory cells instead of one though I increment it only once.
Here is the source code to my program
#include <stdio.h>
void main()
{
char** txt;
char* baseAddress;
txt = (char **)malloc(5*sizeof(char*));
*txt = (char *)malloc(20*sizeof(char));
baseAddress = *txt;
while (*(*txt) != 'q')
{
(*txt)++;
scanf("%c", (*txt));
printf("%p\r\n", (*txt));
}
*txt = '\0';
printf("%p", baseAddress);
free(baseAddress);
free(txt);
}
the output is like this
>j
>0x9e12021
>0x9e12022
>s
>0x9e12023
>0x9e12024
>
I think there may be something wrong with the pointers.
How do I go about accomplishing this? and sorry for the bad english
What exacty you code do :
+----------------------------------------------+
| +--------------------------------------+ |
| txt|*txt |*txt+1 |*txt+2 |*txt+3 |*txt+4 | |
| +--------------------------------------+ |
| ^ ^ no memory alloc ^ |
| | |_______not used_______| |
| +----+ |
|*txt |____| <------------------------------+---you never give a value here,
| +1 |____| <--j |
| +2 |____| <-- '\n' |
| +3 |____| <--s |
| +4 |____| <-- '\n' |
| . . |
| . . |
| . ____ |
| +19 |____| |
+----------------------------------------------+
So you need :
re-write you while loop and deal with the '\n'
when user type q , alloc new string memory and collect user input .
Suggust:
In you fisrt string
Use txt[0] instead of *txt , use txt[0][i] and i++ instead of **txt and (*txt)++ .
Hope can help. :-)
You are forgetting about the newline character.
For instance, you are probably imagining your input to be "js". However, since you are hitting the enter key, it is actually "j\ns\n".
So, you are entering two characters at a time, and it is reading two characters at a time. Your code is behaving just as it should.