问题
I am working on creating my own version of strncpy
. My code seems to accept the input fine, but the program terminates after the input is entered. strncpy
also seems to pad the copied function with nulls if it's shorter than the first - what is the point of that and how do I implement that in my code?
#include <stdio.h>
#include <stdlib.h>
#define SIZE 50
#define STOP "quit"
char *copywords(char *str1, char *str2, int n);
int main(void) {
char words[SIZE];
char newwords[SIZE];
int num;
int i = 0;
int j = 0;
printf("Type a word, and the # of chars to copy, or type 'quit' to quit: ");
fgets(words, SIZE, stdin);
scanf_s("%d", &num);
if (words == STOP) {
printf("Good bye!\n");
return 0;
}
copywords(words, newwords, num);
printf("The word was");
puts(words);
printf("and the copied word is");
puts(newwords);
}
char *copywords(char *str1, char *str2, int n) {
int i;
for (i = 0; i < n; i++) {
str2[i] = str1[i];
}
return str2;
}
回答1:
The short answer is: DO NOT USE strncpy()
.
You can read why here: https://randomascii.wordpress.com/2013/04/03/stop-using-strncpy-already/
The semantics of strncpy
are obscure, widely misunderstood and error prone. The size argument is the size of the destination array, not some limit to the number of characters to copy from the source. If the source string length is size
or larger, the destination will not be null terminated and if it is shorter, the remainder of the destination will be filled with null bytes ('\0'
).
The reasons for these choices are historical: strncpy()
was used to copy filenames into a memory structure for an archaic file system where filenames were limited in length.
The lack of null termination is so error prone that this function should never be used in production code, because the programmer or the maintainer will all too easily misunderstand the code's actual behavior and create bugs by modifying it.
If you must re-implement it as an assignment, you must implement the exact semantics. It you just want to have a handy string function that copies a string with truncation, choose a different name and probably a different argument order.
Here are examples of both:
char *strncpy_reimplemented(char *dest, const char *src, size_t n) {
size_t i;
for (i = 0; i < n && src[i] != '\0'; i++) {
dest[i] = src[i];
}
while (i < n) {
dest[i++] = '\0';
}
return dest;
}
char *pstrcpy(char *dest, size_t size, const char *src) {
size_t i;
if (size > 0) {
for (i = 0; i < size - 1 && src[i] != '\0'; i++) {
dest[i] = src[i];
}
dest[i] = '\0';
}
return dest;
}
Your copywords
function has problems:
- You do not null terminate the destination if the source string is longer than
size-1
- You dereference the source string beyond its length if it is shorter than
size-1
- You do not check if the value typed by the user is within the proper bounds for the source and the destination arrays.
You have further problems:
(words == STOP)
does not check whether the string read byfgets()
isquit
. You must first remove the trailing newline from the buffer and usestrcmp()
to compare strings:words[strcspn(words, "\n")] = '\0'; if (!strcmp(words, "quit")) { printf("Good bye!\n"); return 0; }
Here is a corrected and simplified version of your code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *copywords(char *dest, const char *source, size_t n);
int main(void) {
char words[50];
char newwords[50];
int num;
for (;;) {
printf("Type a word, or type 'quit' to quit: ");
if (scanf("%49s", words) != 1) {
printf("Invalid input!\n");
return 0;
}
if (!strcmp(words, "quit")) {
printf("Good bye!\n");
return 0;
}
printf("Type the # of chars to copy: ");
if (scanf("%d", &num) != 1) {
printf("Invalid input!\n");
return 0;
}
copywords(newwords, words, num);
printf("The word was %s\n", words);
printf("and the copied word is %s\n", newwords);
}
}
char *copywords(char *dest, const char *source, size_t n) {
size_t i;
for (i = 0; i < n && source[i] != '\0'; i++) {
dest[i] = source[i];
}
dest[i] = '\0';
return dest;
}
回答2:
Problem is you dont add terminating character at the end of your sting after copying
for (i = 0; i < n; i++)
{
str2[i] = str1[i];
}
str2[i] = '\0';
Why are you returning str2 if you arent using it?
Also i think you need cant compare by == operator
Edit:
Full Code
#include <stdio.h>
#include <stdlib.h>
#define SIZE 50
#define STOP "quit"
void copywords(char *str1, char *str2, int n);
int main(void)
{
char words[SIZE];
char newwords[SIZE];
int num;
int i = 0;
int j = 0;
printf("Type a word, and the # of chars to copy, or type “quit” to quit: ");
fgets(words, SIZE, stdin);
scanf("%d", &num);
copywords(words, newwords, num);
printf("The word was ");
puts(words);
printf("and the copied word is ");
puts(newwords);
return 0;
}
void copywords(char *str1, char *str2, int n)
{
int i;
for (i = 0; i < n; i++)
{
str2[i] = str1[i];
}
str2[i] = '\0';
}
来源:https://stackoverflow.com/questions/40834173/c-create-own-version-of-strncpy