Printf prints more character than those contained in my string [closed] - c

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I have to write a program that acts like a shell. I wrote the function that gets the input from the user. I also wrote the function that splits it into arguments. The first time I type something, it works well, but the second time, it prints different characters after the ones that I gave it. I don't have to print it in the program. I was just doing it to see if it works correctly. I read a bunch of stuff online, but I can't figure out my error. I suppose it is in makeArgs(), but I can't pinpoint it.
Also, when I give it an input, the readline function adds a \n at the end of the string. I suppose it is from the fact that I press the enter key. I managed to solve the issue, by manually replacing it, but I would like to know if it is normal.
Any help really be appreciated.
Thank You
Screenshot of Xterm after 2 inputs.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int getText();
int makeArgs();
char *textEntre;
size_t nbCharacters;
char **arguments;
int main (void)
{
while (1){
getText();
int nbArguments = makeArgs();
for(int i =0; i<5; i++){
printf("%s \n",arguments[i]);
}
for(int i=0; i<nbArguments; i++){//free the char ptrs at the end
free(arguments[i]);
}
}
free(textEntre);
free(arguments);
return 0;
}
int getText(){
size_t buffersize = 0;
nbCharacters = getline(&textEntre, &buffersize, stdin);
textEntre[nbCharacters-1] =' '; // when I press enter it regiter the enter as \n so I replace it with a space
return 0;
}
int makeArgs(){
arguments = (char **)malloc(sizeof(char*)*20);
int i;
int j = 0;
int k = 0;
int nbElem = 20; //the number of ptrs that can be in arguments
for(i = 0; i<nbCharacters; i++){
if(i == 20){ //increases the memory allocated if there are more than 20 arguments
nbElem = nbElem *2;
arguments = (char **)realloc(arguments, sizeof(char*)*nbElem);
}
if(textEntre[i] == '"'){ //checks for ""
i++;
while(textEntre[i] != '"'){
i++;
}
}
if(textEntre[i] == ' ' && textEntre[i-1] == ' '){ // eliminates useless spaces
j++;
}
else if(textEntre[i] == ' '){ //save a single argument
char * chptr;
chptr = (char *)malloc(i-j+1); //giving +1 for the \0 at the end
strncpy(chptr, &textEntre[j], i-j);
arguments[k] = chptr;
k++;
j = i +1;
}
}
return k;
}

chptr = (char *)malloc(i-j+1); //giving +1 for the \0 at the end
You properly allocated memory for that terminating \0, but where do you actually add that "\0 at the end"?
strncpy(chptr, &textEntre[j], i-j);
strncpy does not necessarily zero-terminate the destination buffer. You have to do it yourself.
In fact, in this specific application strncpy is a rather inappropriate function: it does not give you anything over ordinary memcpy and might be less efficient. You could just do
memcpy(chptr, &textEntre[j], i - j);
with potentially better efficiency. And, again, don't forget to zero-terminate the destination buffer.
Or you can use sprintf for the same purpose as follows
sprintf(chptr, "%.*s", i - j, &textEntre[j]);
which will produce a properly zero-terminated string in the destination. (Albeit you won't see sprintf used that way very often.)

Related

Time Limit When Solving this problem in C [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
Upper Lower
Bibi also wants to challenge Jojo and Lili. She has a string S with N as its length. The string can contain
uppercase and lowercase characters. Then she will do an iteration from the start of the string, if the K-th
character is an uppercase character, then she will change all the characters after it, such that uppercase
character will become lowercase and lowercase character will become uppercase. After the end of the
iteration, she will ask Jojo and Lili what is the string.
Format Input
1.The first line of the input will contain an integer T, the number of test cases.
2.Each test case will contain a string S and an integer N as its length.
Format Output
For each test case, print "Case #X: " (X starts with 1). Then on the same line, print the string after the
iteration.
Constraints
1 <= T <= 10
1 <= N <= 100000
The string will only consist of uppercase and lowercase characters.
This is my solution. But it keeps getting TLE.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(){
int room,len;
scanf("%d",&room);
char words[100000];
for(int i = 0; i<room; i++){
scanf("%s %d",words,&len);
char next[100000];
int j = 0;
printf("Case #%d: ",i+1);
while(j<len){
int k = j+1;
if(isupper(words[j])){
while(k<len){
if(isupper(words[k])){
words[k] = tolower(words[k]);
}else{
words[k] = toupper(words[k]);
}
k++;
}
}
//printf("%c",words[j]);
j++;
}
printf("%s",words);
printf("\n");
}
return 0;
}
Need help for better solution.
I think the TLE comes from nested loops, but I can't figure it out without nested loops.
In the "new algorithm" department - you've implemented the algorithm as stated. However, that means you're spending a lot of time (the majority of the time, I'll guess) looping through the string, changing the case of characters, potentially multiple times. You don't actually need to do this. Keep a counter of the number of uppercase characters you've found, initially set to zero. When you examine a character, check the counter. If the counter is odd (i.e. if (counter & 1)...), reverse the case of the character you're currently looking at (change upper to lower, lower to upper). Having done that, test to see if the character you're currently looking at is uppercase (it may have just changed to that). If so, increment the counter. Then proceed to the next character.
This can be done in-place and in a single pass, without any nested loops.
So your loop over the string looks something like
for (i = 0, counter = 0 ; i < strlen(string) ; ++i)
{
if (counter & 1) /* if counter is odd */
if (isupper(string[i])) /* if character [i] is upper case */
string[i] = tolower(string[i]); /* convert character [i] to lower case */
else
string[i] = toupper(string[i]); /* convert character [i] to upper case */
if(isupper(string[i])) /* if character [i] is now upper case */
counter += 1; /* increment the counter */
}
Best of luck.
You can try this with some pointers magic. Also, try to separate your program into functions, so each part of your code has a clear purpose. Finally, scanf is not a very good solution to get user input: if user enters more characters than expected, it can break your program (or your system if you use Windows). I've just used this scan_str as an example.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
/* Helper function to swap a character case */
char swap_case(char c) {
if(isupper(c))
return tolower(c);
return toupper(c);
}
/* Our iteration test case */
char*test_iterate(char*str) {
char *p, *p0;
/* Don't swap until first upper char is found */
int swap = 0;
/*
* - Initialize both pointers to beginning of string
* - Iterate until a 0 is found (end of string)
* - Each iteration, "advance" pointer by one
*/
for(p0 = p = str; *p != 0; p++) {
/* If is upper, begin to swap case */
if(isupper(*p))
swap = 1;
*p = swap ? swap_case(*p) : *p;
}
/* Return pointer to begining of word */
return p0;
}
/*
* `scanf("%s", &word)` is not good if you are serious and want to avoid memory overflow
*/
char*scan_str() {
/* Lets begin with 10 bytes allocated */
size_t buf_size = 10;
char c, *word = (char*) malloc(buf_size);
int length = 0;
/* Iterate reading characters from `stdin` until ENTER is found */
while( (c = getc(stdin)) != '\n' && c != EOF ) {
/* If we need more than already allocated, allocate more (10 bytes more) */
if((length + 1) >= buf_size) {
buf_size += 10;
word = realloc(word, buf_size);
if(word == NULL)
return "Some weird error.";
}
/* Save read char to our word/buffer */
word[length] = c;
length++;
}
/* Add word ending character */
word[length] = 0;
return word;
}
int main(void) {
int room;
/* Two dimensional array: list of string pointers */
char**tests;
/*
* Use `scanf` to read an integer
* It's still not good enough, as you need this weird `%*c` to discard ENTER inputs
*/
printf("Insert number of tests to do:\n");
scanf("%d%*c", &room);
/* Allocate memory for `tests`: array of pointers to strings */
tests = (char**) malloc(sizeof(char*) * room);
/* Get input from user */
for(int i = 0; i < room; i++) {
printf("Insert test case #%d:\n", i + 1);
tests[i] = scan_str();
}
/* Print results and free each test memory */
for(int i = 0; i < room; i++) {
printf("Case #%d: %s\n", i + 1, test_iterate(tests[i]) );
free(tests[i]);
}
/* Free `tests` array */
free(tests);
return 0;
}

How do I a split a line of integers into array? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
If a user inputted:
1 2 3 4 5 0
How would I transform it into an array with 5 elements (The 0 integer indicates termination)? Also, in the code I need to ensure it works for up to 500 integers.
I have no clue how to proceed. I am thinking of using gets and saving it into an allocated space:
char *ptr;
ptr = malloc(sizeof(char) * 1000);
fgets(ptr, sizeof(char)*1000, stdin);
The problem here is I am not sure how to allocate the space as each digit will be saved as a character and each integer may have different number of digits.
Afterwards, I am not sure how to split it into array.
Could someone advise me on how to continue or if my method is not good?
I know I have not done a lot but I am really confused. I have looked up on gets(), fgets(), scanf(), fscanf(), and am still not sure.
Thanks!
You can parse the line input by the user with sscanf() or strtol():
#include <stdio.h>
int main() {
char buf[256];
int array[5];
if (fgets(buf, sizeof buf, stdin)) {
if (sscanf(buf, "%d%d%d%d%d", &array[0], &array[1], &array[2], &array[3], &array[4]) == 5) {
// array has the 5 numbers input by the user.
printf("%d %d %d %d %d\n", array[0], array[1], array[2], array[3], array[4]);
}
}
return 0;
}
For generic code that works up to 500 numbers, you can just use scanf() in a loop:
#include <stdio.h>
int main() {
int array[500];
int i, n;
for (n = 0; n < 500; n++) {
if (scanf("%d", &array[n]) != 1) {
printf("invalid input\n");
return 1;
}
if (array[n] == 0) {
// 0 indicates termination
break;
}
}
// the array has n valid non-zero numbers
printf("The numbers are:\n");
for (i = 0; i < n; i++) {
printf(" %d\n", array[i]);
}
return 0;
}
You could use a character array with a combination of fgets() and strtok().
First declare a character array str and set a flag variable.
char str[100];
int flag=1;
flag may be made 0 when input 0 is found.
As long as flag is 1 use fgets() to read a line of input (provided fgets() is successful) as in
while(flag==1 && fgets(str, sizeof(str), stdin)!=NULL)
{
.....
.....
}
Now inside this loop, use strtok() to tokenize the string in str using space and \n as delimiters. \n is made a delimiter because fgets() reads in the trailing \n to str as well.
for(ptr=strtok(str, " \n"); ptr!=NULL; ptr=strtok(NULL, " \n"))
{
n=atoi(ptr);
if(n==0)
{
flag=0;
break;
}
printf("\n%d", n);
}
Convert the tokens produced by strtok() to integers. I used atoi() for brevity but it is not the best way. strtol() might be a good idea. See here.
I would suggest something like this
#include "rlutil.h" //a good library similar to conio.h or it's Linux equivalent but cross-platform. You have to include it manually and download it at github.
int i = 0;
int num = 1;
char input;
int array[255];
for (i = 0; num = 0; i++)
{
input = getchar();
num = input - '0';
array[i] = num;
printf("%i ", num);
}
Just pay attention to the size of the array.
Furthermore you could parse the string you got with fgets with strtok. If you want I can edit this post later and include this variant.

Multiplying the numbers of a String [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I want to multiply the numbers in a given string which has one or more spaces.
Example:
If i input 52 26 23
the output should be 31096.
I've written this code but its not working:
#include <stdio.h>
int main()
{
char input[30];
int i, num = 0, v = 1;
gets(input);
for (i = 0; input[i] != '\0'; i++)
{
if(input[i] == 32)
{
v = v * num;
if(input[i+1] != 32)
{
num = 0;
continue;
}
}
num = (num * 10) + (input[i] - 48);
}
printf("%d",v);
return 0;
}
Try this one
#include <stdio.h>
#include <string.h>
int main()
{
char str[30];
char *token;
long int mul = 1;
gets(str);
token = strtok(str, " ");
while (token != NULL)
{
mul = mul * atoi(token);
token = strtok(NULL, " ");
}
printf("%ld",mul);
return 0;
}
The problem lies in your nested if statement. Once it enters the first if statement, that means input[i]==32, therefore it can never enter the next if statement where input[i]!=32.
I also have some suggestions for improving readability. Instead of using numbers to represent the characters, use the character literals themselves!
Another thing, you only have space for 30 characters in your input buffer. If a user attempts to enter more than this, you will have a buffer overflow.
Lastly, if the user puts more than one space between numbers, the output will become 0. That may be something you may or may not want to handle.
Edit: Before, the call to gets was only grabbing characters up to the first whitespace character. I've fixed this issue with a format string in a call to scanf instead. Buffer overflow problem still applies. Also, it was not multiplying with the last parsed integer, so I added code for that after the loop. Another note, this will only work for non-negative integers, if that's something you weren't aware of initially. The code just assumes the input is nice.
Edit 2: support for input with any number of spaces before, between, or after inputs.
#include <stdio.h>
int main() {
char input[30];
int i, num = 0, v = 1;
scanf("%[^\n]s", input);
// skip leading spaces
for(i = 0; input[i] == ' '; i++);
// parse remaining input
while(input[i] != '\0') {
if(input[i] == ' ') {
v *= num;
num = 0;
// skip subsequent spaces
while(input[++i] == ' ');
continue;
}
num *= 10;
num += input[i] - '0';
i++;
}
// ignore trailing spaces
if(input[i - 1] != ' ') {
// get last parsed integer
v *= num;
}
printf("%i\n", v);
return 0;
}

Trouble with C program blank output [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
int i=0,j=0;
char string[100], string2[100];
scanf("%s",&string);
while (string[i]!='\0'){
if(string[i]=='a' || string[i]=='e' || string[i]=='i' || string[i]=='o' || string[i]=='u' || string[i]=='A' || string[i]=='E' || string[i]=='I' || string[i]=='O' || string[i]=='U'){
string[i]=string2[j];
}
string[i] = tolower(string[i]);
string[i] = string2[j];
string2[j-1]='.';
}
printf("%s", string2);
return 0;
The question is entering a word and then removing all vowels, adding '.' after every constant and making all upper case letters lower case.
Since string is an array, you don't use & when passing it to scanf(), this gives you a double pointer and is an error. Any time you find yourself with a 10 clause if statement, you're just asking for problems (e.g. easy to get tripped up by typos.) You can simplify this test with index() and a string containing all the vowels. It wouldn't hurt to comment as you write your code to indicate which of the requirements each section implements. The i variable needs to be incremented every time through the loop, the j variable needs to be incremented every time a new character is added to string2. After the scanf(), you shouldn't be assigning into string, treat it as readonly, only assign into string2. And j-1 shouldn't happen. Finally, since string2 isn't intialized, there may be garbage in it and you haven't null terminated it. Putting it all together:
#include <ctype.h>
#include <stdio.h>
#include <strings.h>
#define VOWELS "AEIOUaeiou"
int main()
{
char string[100], new_string[100] = { 0 };
// enter a word
scanf("%s", string);
for (int i = 0, j = 0; string[i] != '\0'; i++)
{
// remove all vowels
if (index(VOWELS, string[i]) == NULL)
{
// make all upper case letters lower case
new_string[j++] = tolower(string[i]);
if (isalpha(string[i]))
{
new_string[j++] = '.'; // add '.' after every consonant
}
}
}
printf("%s\n", new_string);
return 0;
}
I'm assuming "after every constant" was meant to read "after every consonant", otherwise please clarify what you mean by constant.

programming in C involving strings [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
1.actually I want to first give a number N (no. of strings I want to enter) as an input then in next line a string using gets().But when I press enter then the no. of strings I could enter is N-1.I tried using printf("\n") but it didn't work.Please anyone could help me in this.eg:
//code
int N,i,arr[N];
char str[50];
scanf("%d",&N) //no. of strings required
for(i=0;i<N;i++)
{
gets(str);
arr[i]=strlen(a);
}
for(i=0;i<N;i++)
{
printf("%d\n",arr[i]);
}
i want to enter my input to be like this:
2 //no. of strings
ABCFD //string 1
ASWD //string 2
//But actually what i am getting using printf("\n")
and output:
5
4
but what i am getting:
2
//blank space
ASWD //string 2
and output
0
4
After entering a value for N there remains a newline in the input buffer, which is accepted by the following gets as a blank input. In any case gets is a deprecated function: please use fgets such as like this. I've printed each entry to show there is a newline at the end of each, and removed that newline.
#include <stdio.h>
#include <string.h>
int main(void) {
int N, i;
char str[50];
printf("Enter number of cases\n");
scanf("%d%*c", &N); // read newline too, but discard
for(i=0; i<N; i++)
{
printf("\nEnter string\n");
if (fgets(str, sizeof str, stdin) == NULL)
return 1;
printf("Shows newline >>%s<<\n", str); // show that newline is retained
str [ strcspn(str, "\r\n") ] = 0; // remove trailing newline
printf("After removal >>%s<<\n", str); // show that newline was removed
}
return 0;
}
Program output
Enter number of cases
2
Enter string
one
Shows newline >>one
<<
After removal >>one<<
Enter string
two
Shows newline >>two
<<
After removal >>two<<
Try it --
int lineNumbers;
scanf("%d", &lineNumbers);
char **linesOfString = (char**) malloc(lineNumbers * sizeof(char *));
int i;
for(i = 0; i < lineNumbers; i++) {
fflush(stdin);
linesOfString[i] = (char *) malloc(255 * sizeof(char));
scanf("%s", linesOfString[i]);
}
for(i = 0; i < lineNumbers; i++) {
printf("%s", linesOfString[i]);
}
free(linesOfString);
return 0;
It sounds like you are not getting the number of strings expected, is this correct?
If this is the case, look at your looping code.
The most likely newbie mistake is with indexing. Arrays in C are 0 indexed.
This means that if you have int test[3], the indexes of test will be 0, 1, and 2. This means that the highest index WILL be N-1.
So, make sure that the first string you are accepting is being placed into index 0, and not index 1.

Resources