I just started learning programming, and I started with C, and I am just goofing around and trying to make a function that changes a letters in a string from uppercase to all lowercase, and then return it in an array of lowercase letters...
My code doesn't work. And I'm tired of googling. can somebody please help me please?
Here is what I have up until now:
#include <ctype.h>
#include <cs50.h>
#include <stdio.h>
#include <string.h>
string lowercase(char inlower[]);
int main(void)
{
string word = get_string("Type in a word: ");
char inlower[strlen(word)];
printf("You typed: %s\n", word);
}
string lowercase(string word)
{
for (int i = 0, len = strlen(word); i < len; i++)
{
inlower[i] = tolower(word[i]);
// printf("%c", inlower[i]);
}
return inlower[];
}
You need to work on word and return word, not word[]. inlower is local to main and can't be used in lowercase, unless you pass it along as a parameter along with word.
Also note that you should cast the char in your char[] (string) to unsigned char before using it with tolower. If char is signed and the char[] contains negative values, calling tolower will cause undefined behavior.
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
string lowercase(string word)
{
for (unsigned i = 0, len = strlen(word); i < len; i++)
{
word[i] = tolower((unsigned char) word[i]);
}
return word;
}
int main(void)
{
string word = get_string("Type in a word: ");
printf("You typed: %s\n", lowercase(word));
}
If you do want to put the lowercase word in inlower that you've declared in main, you also need to make it big enough for what you have in word. strlen(word) is one char short since every string must be terminated with a \0 char.
string lowercase(string inlower, string word)
{
unsigned i = 0;
for (unsigned len = strlen(word); i < len; i++)
{
inlower[i] = tolower((unsigned char) word[i]);
}
inlower[i] = '\0';
return inlower;
}
int main(void)
{
string word = get_string("Type in a word: ");
char inlower[strlen(word) + 1]; // correct size
lowercase(inlower, word); // pass `inlower` in to `lowercase` too
printf("You typed: %s\n"
"In lowercase: %s\n", word, inlower);
}
Alternative version without doing strlen inside lowercase too:
string lowercase(string inlower, string word)
{
string dest = inlower;
for(;*word; ++word, ++dest)
{
*dest = tolower((unsigned char) *word);
}
*dest = '\0';
return inlower;
}
Related
I'm confused why I get an empty string when I print out reversed. Printing out the character at each iteration seems to be working ok.
Output:
original string: testing
g
n
i
t
s
e
t
reversed:
#include <stdio.h>
#include <string.h>
void reverse_string(char string[]) {
int str_len = strlen(string);
char reversed[20];
int j = 0;
for (int i = strlen(string); i>= 0; i--) {
char tmp = string[i];
reversed[j] = tmp;
printf("%c\n", reversed[j]);
j++;
}
reversed[j] = '\0';
printf("reversed: %s", reversed);
}
int main (void) {
char string[8] = "testing";
printf("original string: %s", string);
reverse_string(string);
return 0;
}
i starts at strlen(string), which points to the terminating '\0' character. That character is copied into position 0 in the reversed string, so any characters after that are not considered part of the string.
for (int i = strlen(string); i>= 0; i--) {
char tmp = string[i];
string[strlen(string)] is by definition always the string termination character '\0'. You have to start your loop at strlen(string)-1.
I want to print the length of each word in a string.
I have tried but not getting right answer. After running the code it will print the length of each word after the word instead of printing before the each word.
char str[20] = "I Love India";
int i, n, count = 0;
n = strlen(str);
for (i = 0; i <= n; i++) {
if (str[i] == ' ' || str[i] == '\0') {
printf("%d", count);
count = 0;
} else {
printf("%c", str[i]);
count++;
}
}
I except the output is 1I 4Love 5India, but the actual output is I1 Love4 India5.
You can use strtok as Some programmer dude sugested. You may want to make a copy of the original string as strtok modifies the passed string. Also strtok is not thread-safe and must be replaced with strtok_r when working with multi-threaded programs.
#include <stdio.h>
#include <stdlib.h>
/* for strtok */
#include <string.h>
int main() {
char str[20] = "I Love India";
int n;
char* tok = strtok(str, " ");
while (tok != NULL) {
n = strlen(tok);
printf("%d%s ", n, tok);
tok = strtok(NULL, " ");
}
return EXIT_SUCCESS;
}
You want to compute and print the length of each word before you print the word.
Here is a simple solution using strcspn(), a standard function that should be used more often:
#include <stdio.h>
#include <string.h>
int main() {
char str[20] = "I Love India";
char *p;
int n;
for (p = str; *p;) {
if (*p == ' ') {
putchar(*p++);
} else {
n = strcspn(p, " "); // compute the length of the word
printf("%d%.*s", n, n, p);
p += n;
}
}
printf("\n");
return 0;
}
Your approach is wrong as you print the word before the length. So you need to calculate the length first then print it and then print the word.
It could be something like:
int main(void)
{
char str[20]="I Love India";
size_t i = 0;
while(str[i])
{
if (str[i] == ' ') // consider using the isspace function instead
{
// Print the space
printf(" ");
++i;
}
else
{
size_t j = i;
size_t count = 0;
// Calculate word len
while(str[j] && str[j] != ' ')
{
++count;
++j;
}
// Print word len
printf("%zu", count);
// Print word
while(i<j)
{
printf("%c", str[i]);
++i;
}
}
}
}
The basic idea is to have two index variables for the string, i and j. The index i is at the words first character and index j is used for finding the end of the word. Once the end of word has been found, the length and the word can be printed.
This is what you want:
#include <stdio.h>
#include <string.h>
int main()
{
char str[20]="I Love India";
char buf[20];
int i,n,count=0;
n=strlen(str);
for (i=0; i <= n; i++) {
if(str[i]==' ' || str[i]=='\0'){
buf[count] = '\0';
printf("%d", count); /* Print the size of the last word */
printf("%s", buf); /* Print the buffer */
memset(buf, 0, sizeof(buf)); /* Clear the buffer */
count = 0;
} else {
buf[count] = str[i];
count++;
}
}
return 0;
}
You will want to keep a buffer of the word that is currently being counted. (buf)
Increment count each time its not a space or 0/. Then, when it is a space or a 0/, print count first, then buf. Then, we will clear buf and set count to 0, so that the variable i is still incrementing through the entire string str, but we are inserting the words into buf starting from 0.
I'm trying to figure out how to count the occurrences of each word in a string entered by the user. I want to use an array for the input and copy each element/word into another array(words), only if the word hasn't been copied already. If it's already been copied, I want to just increment the number of occurrences by using a parallel counter array(count). So far, what I have compiles, but when I run the program it just gives me 0 for all of the count values, and it still prints every word in the string even if it's already been printed before. Any help will be greatly appreciated!
#include <stdio.h>
#include <string.h>
#define STR_LEN 1000
int read_line(char *str, int n);
int main() {
char input[STR_LEN + 1];
char *token;
char words[50];
char *p1;
char *p2;
int i;
int count[50] = { 1 };
printf("Please enter a string: ");
read_line(input, STR_LEN); //Calls the readline function
printf("Input: %s\n", input);
for (i = 0; i < strlen(input); i++) {
p1 = &input[i];
p2 = &words[i];
if (strstr(p1, input) == 0) {
strcpy(p2, p1);
} else
count[i]++;
}
printf("Output: \n");
token = strtok(words, " ,.!"); //tokenizes the first word in the string
while (token != NULL) {
printf("%s\t\t%d\n", token, count[i]);
token = strtok(NULL, " ,.!"); //tokenizes subsequent words in the string
}
return 0;
}
int read_line(char *s1, int n) {
int ch, i = 0;
while ((ch = getchar()) != '\n') {
if (i < n) {
*s1++ = ch;
i++;
}
}
*s1 = '\0'; //terminates string
return i; //number of characters stored
}
You should use an array of strings instead of an array of characters for words:
char *words[50];
You should allocate copies of the words with strdup().
You main loop is inconsistent, you are not matching words, you lookup string fragments for each offset into the string. Move the tokenization code to the loop and match strings, not characters.
I wanted to split an array to 2 arrays that the first one contains the lowercased letters of the original array and the second one contains the uppercased letters and from some reason it prints some unrelated chars.
#include <stdio.h>
#include <string.h>
#define LEN 8
int main(void)
{
char str[] = "SHaddOW";
char smallStr[LEN], bigStr[LEN];
int i = 0;
int indexSmall = 0;
int indexBig = 0;
for (i = 0; i <= LEN; i++)
{
if (str[i] <= 'Z')
{
smallStr[indexSmall] = str[i];
indexSmall++;
}
if (str[i] >= 'Z')
{
bigStr[indexBig] = str[i];
indexBig++;
}
}
printf("1: ");
puts(smallStr);
printf("2: ");
puts(bigStr);
system("PAUSE");
return 0;
}
Don't define length before you create the string to test.
Create it's length after defining the string to test.
Copy the characters as you encounter them, but as #Ed Heal says you must add a null terminator so that you can print out the two strings (they aren't really strings until they are null terminated).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main (void)
{
char str[] = "SHaddOW";
int len = strlen(str) +1;
char smallStr[len], bigStr[len];
char term[] = {'\0'};
int n, s, b;
s=0;
b=0;
for(n=0; n<len; n++) {
if(islower(str[n])) {
memcpy(smallStr +s, str +n, 1);
s++;
} else if (isupper(str[n])){
memcpy(bigStr +b, str +n, 1);
b++;
}
}
memcpy(smallStr + s, term, 1);
memcpy(bigStr + b , term, 1 );
printf("Upper: %s\n", bigStr);
printf("Lower: %s\n", smallStr);
}
Output:
Upper: SHOW
Lower: add
Add this to the if structure (and other code to support it)
} else {
memcpy(anyStr +a, str +n, 1);
a++;
}
then:
char str[] = ".S1H2a3d4d5O6W.";
and:
printf("Anything else: %s\n", anyStr);
returns:
Upper: SHOW
Lower: add
Anything else: .123456.
A more compact approach with (perhaps) more meaningful variable names:
#include <stdio.h>
#include <ctype.h>
#include <stdint.h>
#include <string.h>
int main ( void ) {
const char str[] = "SHaddOW";
size_t len = strlen(str); /* better to get actual length */
char lowers[len + 1]; /* add one for the nul char */
char uppers[len + 1]; /* (see below) */
int c;
int i = 0;
int n_upper = 0;
int n_lower = 0;
while ((c = str[i++]) != '\0') {
if (isupper(c)) uppers[n_upper++] = c; /* no need to reinvent */
if (islower(c)) lowers[n_lower++] = c; /* the wheel here */
}
uppers[n_upper] = '\0'; /* the nul char ('\0') marks */
lowers[n_lower] = '\0'; /* the end of a C "string" */
printf("1: %s\n", lowers);
printf("2: %s\n", uppers);
return 0;
}
Notes
If you are super concerned about efficiency you could add an else before if (islower...
Adding const means you "promise" the characters in the array won't be changed.
The type size_t is an integer type, but may be larger than int. It is the correct type for the return of strlen(). It is defined in <stdint.h>. None the less, using int will almost always work (on most systems a string would have to be 'yooooge' for its length to be bigger than an int can hold).
The variable c is declared as int instead of char because int is the proper type for the isXXXXX() functions (which are defined in <ctype.h>). It is also a good habit to get into because of the parallels between this loop and another common idiom while ((c = fgetc(fp)) != EOF) ....
You should consider using isupper() and islower() functions. Code would be cleaner. And what if you have some non alpha characters? Your conditions won't work.
for (i = 0; i < LEN; i++)
{
if (islower(str[i]))
{
smallStr[indexSmall] = str[i];
indexSmall++;
}
else if (isupper(str[i]))
{
bigStr[indexBig] = str[i];
indexBig++;
}
}
As #Ed Heal mention. To avoid printing rubbish, after for loopt you should add a null characters to arrays.
smallStr[indexSmall] = '\0';
bigStr[indexBig] = '\0';
I'm stuck. I've got quite a big programming assignment and most of it looks easy, the part I'm stuck on is splitting a string of text into individual words in an array and then sorting them in alphabetical order.
E.g. if the string contained the following: "I am stuck. Please help me stack exchange" it would save the words in an array and output them in the following order:
am
exchange
help
i
me
please
stack
stuck
Could you guys please help?
EDIT: Here's what I have so far:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char str[] = "This is a test String, anything else? lol";
char *hhh;
int i;
for(i=0;str[i];i++){
str[i]=tolower(str[i]); //Converts the string to lower case
}
//Breaks the string into separate words based on spaces and some
//punctuation (Anything which signals the end of a word)
hhh = strtok(str," ,.-:;?!");
while(hhh != NULL){
printf("%s \n",hhh);
hhh = strtok(NULL, " ,.-:;?!");
}
}
As you can see I've converted the words into lower case r and I can output them but I have no idea how to sort them in alphabetical order. Looked into bubble sorting and I understand it but I don't understand how to use it to accomplish what I need.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int cmp(const void *a, const void *b){
return strcmp(*(const char **)a, *(const char **)b);
}
int main(){
char str[] = "This is a test String, anything else? lol";
char *word, *words[strlen(str)/2+1];
int i, n;
for(i=0;str[i];i++){
str[i]=tolower(str[i]);
}
i=0;
word = strtok(str, " ,.-:;?!");
while(word != NULL){
words[i++] = word;
word = strtok(NULL, " ,.-:;?!");
}
n = i;
qsort(words, n, sizeof(*words), cmp);
for(i=0; i<n; ++i)
puts(words[i]);
return 0;
}
My code is pretty "manual" meaning that I don't use stuff like strtok or tolower. I manually loop through everything myself. If you don't like that, just replace the corresponding parts with those functions. Here you go:
#include <stdio.h>
#include <string.h>
#define _WLEN 32 // maximum length of each word
#define _NWORDS 256 // maximum number of words in the sentence
void word_swap(char** w1, char** w2);
int main(int argc, const char * argv[]) {
char* sentence = "The quick brown fox jumps over the lazy dog."; // the sentence
char to_ignore[10] = ".,-\"'!?()"; // characters that are ignored
char words[_NWORDS][_WLEN]; // words will be stored here
int i, j, k=0, l=0, word_count, swapped=0; // some variables that will be needed
/* First we loop through the sentence to separate the words */
for (i=0; i<_NWORDS*_WLEN; i++) {
/* If we reach the end of the sentence, finish up the last word with '\0' and quit the loop */
if (*(sentence+i) == '\0') {
words[k][l] = '\0';
word_count = k+1;
break;
}
/* Check if the current character is one that we want to ignore. If so, skip to the next character. */
for (j=0; j<10; j++) {
if (to_ignore[j] == *(sentence+i)) goto END_FOR;
}
/* If the current character is not a space, add it to a word */
if (*(sentence+i) != ' ') {
words[k][l] = *(sentence+i);
l++;
}
/* ... if it is a space, finish the current word with '\0' and move to the next word */
else {
words[k][l] = '\0';
k++;
l=0;
}
END_FOR:;
}
/* Convert everything to lowercase so it's easy to sort the words */
for (i=0; i<word_count; i++) {
for (j=0; j<_WLEN; j++) {
if (words[i][j] == '\0') break;
/* If the letter is uppercase (ASCII codes 65-90) then add 32 to it, which is the lowercase variant */
if (words[i][j] >= 65 && words[i][j] <= 90) words[i][j] += 32;
}
}
/* Bubble sort the words in alphabetical order */
do {
for (i=0; i<word_count-1; i++) {
if (strcmp(words[i], words[i+1]) > 0) {
word_swap(&words[i], &words[i+1]);
swapped = 1;
break;
} else swapped = 0;
}
} while (swapped != 0);
/* Print the words on the screen */
for (i=0; i<word_count; i++) printf("%s\n", words[i]);
}
void word_swap(char** w1, char** w2) {
char tmp[_WLEN];
memcpy(&tmp, w1, _WLEN);
memcpy(w1, w2, _WLEN);
memcpy(w2, &tmp, _WLEN);
}