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 8 years ago.
Improve this question
The following code returns the first location in the string s1 where any character from the string s2 occurs. Its worst time complexity is O(m+n). How?
#include<stdio.h>
int any(char *s1, char *s2)
{
char array[256];
int i;
if (s1 == NULL) {
if (s2 == NULL) {
return(0);
} else {
return(-1);
}
}
for(i = 0; i < 256; i++) {
array[i] = 0;
}
while(*s2 != '\0') {
array[*s2] = 1;
s2++;
}
i = 0;
while(s1[i] != '\0') {
if (array[s1[i]] == 1) {
return(i);
}
i++;
}
return(-1);
}
It does this in two steps.
It initializes an array of size 256 (representing each of the valid characters for its input strings), and for each letter in s2 (n) marks that characters spot in the array as 1 to indicate that that character is present.
It iterates across the characters in s1 (0 up to m), checking each characters position in the array to see if it is set to "present" (1), which would indicate that it is in the second string. If it is, it returns the index of that character in s1. If none of the characters in s1 are present in s2 (discovered at m), it returns -1.
Since step 1 will always take n (length of s2), and step 2 will take up to m (the length of s1), the worst case is O(m+n), which occurs only when either there are no matches, or only the last character in s1 is present in s2.
Related
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
I was just wondering if someone knows why my while statement I have is not printing out the array that the user is filling in. Below I have attached my code. Thanks so much for your help!
/*
* File: strings.c
*
* Purpose: To create a small program that should read in 2 strings from the
* user, “string1” and “string2”, each of which can NOT be longer
* than 79 characters.
*/
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
// Prints the length of each string (i.e. how many characters each string contains).
const int LENGTH_OF_STRING = 79;
char firstText[LENGTH_OF_STRING + 1 ];
char secondText[LENGTH_OF_STRING + 1 ];
int charPosition = 0;
// Ask user to type in first string
printf("Please enter your first string no longer than %d characters: \n", LENGTH_OF_STRING);
scanf("%[^\n]s", firstText);
fgetc(stdin);
// Ask user to type in second string
printf("Please enter your first string no longer than %d characters: \n", LENGTH_OF_STRING);
scanf("%[^\n]s", secondText);
fgetc(stdin);
// The computer need to print out the users first string
while ((charPosition !=0) && (charPosition < LENGTH_OF_STRING + 1 )){
printf("%c", firstText[charPosition]);
charPosition ++;
}
return (EXIT_SUCCESS);
}
You initialize charPosition at 0 and then test that charPosition does not equal zero in your while loop. The loop is never entered.
Your condition should be:
while ((firstText[charPosition] != '\0') && (charPosition < LENGTH_OF_STRING + 1)) {
If you just had the latter test you would print every character in your buffer, even after the null terminator.
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;
}
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.)
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.
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 9 years ago.
Improve this question
I'd like to ask you about my prog. The main purpose of this one is to fill the "result" array with data collect from "tab1" and "tab2" arrays. Could anybody check, why does results are so weird? Thank you.
#include <stdio.h>
#include <stdlib.h>
void laczenie(char tab1[],char tab2[])
{
int i;
char* result =(char*) malloc(100*sizeof(char));
for(i=0;i<30;i++)
{
if(tab1[i] != '\0') tab1[i]==result[i];
else if (tab2[i] !='\0')tab2[i]==result[i];
else printf(" ");
}
for(i=0;i<30;i++)printf("%c",result[i]);
free(result);
}
int main()
{
char x[10]={'n','a','p','i','s','1'};
char y[10]={'n','a','p','i','s','2'};
//char x[10] = {"napis1"};
//char y[10] = {"napis2"};
laczenie(x,y);
return 0;}
In addition to LihOs answer above this block looks wrong:
if(tab1[i] != '\0')
tab1[i]==result[i];
else if (tab2[i] !='\0')
tab2[i]==result[i];
else printf(" ");
Don't you mean to assign the value in tab1[i]or tab2[i] to result[i]like this?
if(tab1[i] != '\0')
result[i] = tab1[i];
else if (tab2[i] !='\0')
result[i] = tab2[i];
else printf(" ");
Also using magic numbers like in the loops: for(i=0;i<30;i++) is pretty bad practice, you should probably be using a constant for the size value (which you could then use in both the loops and in the array declarations. And why loop to 30 when the arrays is 10 elements only?
In your function you check for null-terminating character:
if(tab1[i] != '\0')
but where is null-terminating character here?
char x[10]={'n','a','p','i','s','1'};
Try:
char x[7]={'n','a','p','i','s','1','\0'};
Also note that tab1[i]==result[i]; compares tab[1] with result[i], if you want to assign the result[i] to tab1[i], use assignment operator =:
tab1[i]=result[i];
if(tab1[i] != '\0')
result[i] = tab1[i];
else if (tab2[i] !='\0')
result[i] = tab2[i];
else printf(" ");`
This is still wrong as by the time you assign tab2 to result i will be already at 6 so you will have to use two for loops i suppose for assign tab1 and tab 2