This question already has answers here:
Remove characters from a string in C
(4 answers)
How to remove the character at a given index from a string in C?
(22 answers)
Closed 1 year ago.
C is a new language for me. So some things I learned in other languages don't work here. I created a program that reads a string from the user, and what happens is when there is a dash (-) in the string, I want to remove it, just remove it, I tried to do that by the conventional method var x = "", but it didn't work. Sure, that's just an example, I know it doesn't work in C, but you got the idea.
Source code
#include <stdio.h>
#include <string.h>
int main()
{
char input[50];
int i;
scanf("%s", input);
for (i = 0; i < strlen(input); i++)
{
if (input[i] == '-')
{
input[i] = "" // Does not remove the dash
}
}
printf("%s\n", input);
return 0;
}
I also tried: input[i] = '\0' and it does not work as well. How can I fix it?
Example of how I want it to be:
Input: 333-55792
Output: 33355792
C is not a high level language. You need to do the manual work of shifting the characters to left skipping dashes:
int from = 0;
int to = 0;
while (str[from] != '\0')
{
if (str[from] == '-')
{
++from;
continue;
}
str[to] = str[from];
++to;
++from;
}
str[to] = '\0';
I don't see a very simple answer in the duplicate. Removing single characters is much easier than removing strings of characters, since we can easily find them.
I will point out that you should not call strlen a lot in C. strlen counts all the characters, so it is O(n), making your loop O(n^2). C uses null terminated strings, so inserting a '\0' ends the string. You can also use this fact to terminate your loop.
There are easier ways to do this using pointers, but for a beginner, I'll give an array like solution
int dashes = 0;
for (i = 0; input[i] != '\0'; i++)
{
if (input[i] == '-')
{
dashes++;
}
else if (dashes > 0)
{
input[i-dashes] = input[i];
}
}
// now, null terminate, could do this changing our loop test, but
// this is easier to understand.
input[i-dashes] = '\0';
Related
I'm a beginner programmer and im trying to solve some exercises and i needed some help with one of them.
The exercise goes like this:
We need to input a string of characters , read it and print out the length of each word.
This is what i did
int main()
{
char str[N+1+1];
int i=0;
int pos=0;
int wordlen=0;
int word[60]={0,};
printf("Please enter the string of characters: ");
gets(str);
while(i<strlen(str))
{
if(!isalpha(str[i]))
{
wordlen=0;
i++;
}
if(isalpha(str[i]))
{
wordlen++;
i++;
pos=i;
}
word[pos]=wordlen;
wordlen=0;;
i++;
}
for(i=0;i<20;i++)
{
if(word[i]==0) // here im just trying to find a way to avoid printing 0's but you can ignore it if you want
{break;}
else
printf("%d ",word[i]);
}
return 0;
}
The problem is that when i try to compile it for example: I input "hi hi hi" its supposed to print 2 2 2 but instead it's printing nothing.
Can i ask for some help?
I failed to follow OP's logic.
Perhaps begin again?
End-of-word
To "count the length of each word", code needs to identify the end of a word and when to print.
Detecting a non-letter and the current word length > 0 indicates the prior character was the end of a word. Note that every C string ends with a non-letter: '\0', so let us iterate on that too to insure loop ends on a final non-letter.
int word_length = 0;
int strlength = strlen(str); // Call strlen() only once
while (i <= strlength) {
if (isalpha(s[i])) {
word_length++;
} else {
if (word_length > 0) {
printf("%d ", word_length);
word_length = 0;
}
}
}
printf("\n");
gets()
gets() is no longer in the C library for 10 years as it is prone to over-run. Do not use it.
we are supposed to use gets. is unfortunate and implies OP’s instruction is out-of-date. Instead, research fgets() and maybe better instruction material.
Advanced
is...() better called as isalpha((unsigned char) s[i]) to handle s[i] < 0.
In general, better to use size_t than int for string sizing and indexing as the length may exceed INT_MAX. That is not likely to happen with OP's testing here.
As part of an assignment, I am supposed to write a small program that accepts an indefinite number of strings, and then print them out.
This program compiles (with the following warning
desafio1.c:24:16: warning: format not a string literal and no format arguments [-Wform
at-security]
printf(words[i]);
and it prints the following characters on the screen: �����8 ���#Rl�. I guess it did not end the strings I entered by using getchar properly with the null byte, and it prints out garbage. The logic of the program is to initiate a while loop, which runs untill I press the enter key \n, and if there are an space, this is a word that will be store in the array of characters words. Why am I running into problems, if in the else statement once a space is found, I close the word[i] = \0, in that way and store the result in the array words?
#include <stdio.h>
#include <string.h>
int main()
{
char words[100][100];
int i,c;
char word[1000];
while((c = getchar()) != '\n')
{
if (c != ' '){
word[i++] = c;
c = getchar();
}
else{
word[i] = '\0';
words[i] == word;
}
}
int num = sizeof(words) / sizeof(words[0]);
for (i = 0; i < num; i++){
printf(words[i]);
}
return 0;
}
Here are some fixes to your code. As a pointer (as mentioned in other comments), make sure to enable compiler warnings, which will help you find 90% of the issues you had. (gcc -Wall)
#include <stdio.h>
#include <string.h>
int main() {
char words[100][100];
int i = 0;
int j = 0;
int c;
char word[1000];
while((c = getchar()) != '\n') {
if (c != ' '){
word[i++] = c;
} else {
word[i] = '\0';
strcpy(words[j++], word);
i = 0;
}
}
word[i] = '\0';
strcpy(words[j++], word);
for (i = 0; i < j; i++) {
printf("%s\n", words[i]);
}
return 0;
}
i was uninitialized, so its value was undefined. It should start at 0. It also needs to be reset to 0 after each word so it starts at the beginning.
The second c = getchar() was unnecessary, as this is done in every iteration of the loop. This was causing your code to skip every other letter.
You need two counters, one for the place in the word, and one for the number of words read in. That's what j is.
== is for comparison, not assignment. Either way, strcpy() was needed here since you are filling out an array.
Rather than looping through all 100 elements of the array, just loop through the words that have actually been filled (up to j).
The last word input was ignored by your code, since it ends with a \n, not a . That's what the lines after the while are for.
When using printf(), the arguments should always be a format string ("%s"), followed by the arguments.
Of course, there are other things as well that I didn't fix (such as the disagreement between the 1000-character word and the 100-character words). If I were you, I'd think about what to do if the user entered, for some reason, more than 1000 characters in a word, or more than 100 words. Your logic will need to be modified in these cases to prevent illegal memory accesses (outside the bounds of the arrays).
As a reminder, this program does not accept an indefinite number of words, but only up to 100. You may need to rethink your solution as a result.
Trying to crack password using brute force but program does not seem to realize when it found the password.
So I tried writing a little program to crack passwords using brute force.
basically I iterate rhough all letter combinations using nested for loops (The passwords needn't be longer than 4 letters), then I use crypt on the password with a given salt (assuming the salt is fixed) to check whether I cracked the password (I have access to the crypted passwords). Now I had the code output what it generates and it looks like it does iterate through all lowercase variants. But somehow it never find the password.
Now I have created the crypted version myself so I know the password is 4 Letters long, that’s not the problem and the program does seems to iterate through all possibilities, I think, so what could be the problem ? Is the if condition wrong ?
Now I guess this is not the most elegant solution for the problem but I think the general Idea is right. But if there is a problem with that nested for loop approach I'd be happy to know that to :).
#define _XOPEN_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <cs50.h>
int main(int argc, string argv[]) {
if(argc < 2) {
printf("Please enter a password to crack! \n");
return 1;
}
char s[4] = "";
for(int i = 0; i <=27; i++) {
if(i == 0)
s[0] = 0;
else
s[0] = i - 1 + 'a';
if(strcmp(crypt(s, "50"), argv[1]) == 0) {
break; }
for(int j = 0; j <=26; j++) {
if(j == 0)
s[1] = 0;
else
s[1] = (j - 1 + 'a');
if(strcmp(crypt(s, "50"), argv[1]) == 0)
break;
for(int k = 0; k <= 26; k++) {
if(k == 0)
s[2] = 0;
s[2] = (k - 1 + 'a');
if(strcmp(crypt(s, "50"), argv[1]) == 0)
break;
for(int l = 0; l <= 26; l++) {
printf("%s \n", s);
if(l == 0)
s[3] = 0;
else
s[3] = (l - 1 + 'a');
if(strcmp(crypt(s, "50"), argv[1]) == 0)
break;
}
}
}
}
if (strcmp(crypt(s, "50"), argv[1]) != 0)
printf("Password not found");
else
printf("%s \n", s);
Declaring char s[4] fails to leave room for a null character terminator when the array has four non-null characters, resulting in behavior not defined by the C standard.
C strings are null terminated, that means, that a string in C is basically an array of bytes/characters (like the one you initialize: char s[4] = "";) with the last byte set to 0.
strcmp goes through two strings(byte arrays) and compares them one by one until it finds a different character or until both strings end, i.e. the currently compared byte is a 0 for both strings. When you initialize your char array s to be 4 bytes, and write 4 non-null bytes into it, strcmp will continue comparing bytes after the end of the array, because it did not hit the end of a string. This can also crash your program or lead to security vulnerabilities, because you continue reading into memory, that you are not supposed to. To get around this, properly terminate your input strings with a null byte and use the strncmp function when possible, which takes an additional parameter, indicating how many characters it should compare at most.
As you correctly identified, the nested loop approach is not the most elegant solution, because you are repeating yourself over and over and the resulting code is very rigid and can only compare up to 4 character passwords. It would be cleaner to have an outer for loop to loop through the possible passwords lengths and then call a function which checks all possible passwords of a certain length (using two nested loops).
If you are just looking to bruteforce some passwords and not actually want to program it yourself, you will probably be better of using some professional tool like https://hashcat.net/hashcat/.
For an assignment I am doing, I have to print out the initials from a string in C (or, an array of characters). To do this, I know that I need to find where the SPACE is, using (int)name[i] == 32 to find if the current character is a SPACE. My only issue with this is that I am having trouble figuring out how I can find the space, and then store the next character in the array of character. (e.g., user enters Mike Baggins, I have to print out MB). I will post my code below, to show you how far I've gotten. Please help, but please don't give me the full solution. Thank you!
#include <cs50.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
string name = get_string(); // gets the user's input
char firstI = name[0]; // stores the first character from the user's input
int len = strlen(name);
if((int)firstI >= 97 && (int)firstI <= 122) // checks if the character is lowercase
{
firstI -= 32; // makes the value uppercase
}
for(int i = 0; i < len; i++)
{
if((int)name[i] == 32) // checks if the character is SPACE
{
printf("I found a space!\n"); // prints out "I found a space"
}
}
printf("%c\n", firstI); // prints out the first initial
}
It's actually simple, see this for example
#include <stdio.h>
#include <ctype.h>
int
main(void)
{
char array[10];
char string[] = "Mike Baggins";
int j;
// Always put the first non-whitespace
// character (we should probably skip all
// spaces first
array[0] = string[0];
// Now start at the character following the first
j = 1;
for (int i = 1; ((string[i - 1] != '\0') && (j < sizeof(array) - 1)); ++i) {
if (string[i - 1] == ' ') {
array[j++] = toupper(string[i]);
}
}
array[j] = '\0';
puts(array);
return 0;
}
All I needed was to know that strings are simply arrays with a special value marking the end of them → '\0'. Of course, you can improve it a lot. For instance, you could count how many initials are there in the input string and allocate enough space to store them all.
Also, this will only work if the interesting character follows the space immediately, but knowing that it's just an array I am sure you can figure out how to extend it to make it ignore consecutive spaces.
I am very new here .. so please excuse me if my question is really unnecessary .. but I think the answer will help me have some faith in myself ..here are two code snippets ..one i got on the website c4learn.com ..
#include<stdio.h>
int main()
{
char s1[100], s2[100];
int i;
printf("\nEnter the string :");
gets(s1);
i = 0;
while (s1[i] != '\0')
{
s2[i] = s1[i];
i++;
}
s2[i] = '\0';
printf("\nCopied String is %s ", s2);
return (0);
}
and the other i wrote myself ..
#include<stdio.h>
int main()
{
char s1[100], s2[100];
int i;
printf("\n Enter the string 1");
gets(s1);
printf("\n Enter the string2");
gets(s2);
for(i=0;i<100;i++)
{
if (s1[i]!='\0')
{
s2[i]=s1[i];
}
}
s2[i]='\0';
printf("\n Copied string is %s ", s2);
return(0);``
}
the problem is while running the code on dev c++ .. the final printf displayed is showing some random characters at the end of the string .. Can anyone help me understand that and which is code is better ? the initial question was ... HOW WILL YOU COPY ONE STRING TO ANOTHER WITHOUT USING ANY INBUILT LIBRARIES ? thank you ..
Your code is not quite right:
Why do you ask for the user input for s2 if you then overwrite it, copying s1?
The for cycle you wrote doesn't stop when s1 is over (I mean the null terminator character '\0') so you are also copying all the chars remaining in s1 after '\0'. If the chars in the array are not initialized (and that's the case for chars after '\0') they of course might result in random characters.
So answering your question, the first code is the right way to do it.
Any way if you want to use a for cycle you could do:
for (i = 0; i < 100; i++) {
s2[i] = s1[i];
if (s1[i] == '\0')
break;
}
You have to break out of the loop when you reach the null terminator character \0. The first code breaks out of the while loop while you're code continues on until i == 100 skipping over the null character. This is why its printing garbage past the original string.
This is what you should do to break out after the null character.
for (i = 0; i < 100; i++) {
s2[i] = s1[i];
if (s1[i] == '\0') break;
}
In the second block of code, after exiting the for loop, i has a value of 100. So you're putting the 0 byte at index 100.
Since an array of size 100 has indexes 0 to 99, you're writing past the end of the array. That causes undefined behavior.
When you're inside of the for loop, you need to break out after you find the null byte.
Also, both programs use gets which is unsafe because it does not perform any bounds checking and may write past the end of the array.