إزالة حرف NewLine Newline من إدخال FGETS ()
سؤال
أحاول الحصول على بعض البيانات من المستخدم وإرسالها إلى وظيفة أخرى في GCC. الرمز شيء مثل هذا.
printf("Enter your Name: ");
if (!(fgets(Name, sizeof Name, stdin) != NULL)) {
fprintf(stderr, "Error reading Name.\n");
exit(1);
}
ومع ذلك ، أجد أنه يحتوي على سطر جديد \n
شخصية في النهاية. لذلك إذا دخلت John
انتهى الأمر بالإرسال John\n
. كيف يمكنني إزالة ذلك \n
وأرسل سلسلة مناسبة.
المحلول
الطريق القبيح قليلا:
char *pos;
if ((pos=strchr(Name, '\n')) != NULL)
*pos = '\0';
else
/* input too long for buffer, flag error */
الطريقة الغريبة قليلاً:
strtok(Name, "\n");
نلاحظ أن strtok
لا تعمل الوظيفة كما هو متوقع إذا دخل المستخدم إلى سلسلة فارغة (أي يضغط فقط إدخال). يترك \n
شخصية سليمة.
هناك آخرون كذلك ، بالطبع.
نصائح أخرى
ربما يستخدم الحل الأبسط إحدى وظائفي المفضلة غير المعروفة ، strcspn()
:
buffer[strcspn(buffer, "\n")] = 0;
إذا كنت تريد أن تتعامل معها أيضًا '\r'
(قل ، إذا كان الدفق ثنائيًا):
buffer[strcspn(buffer, "\r\n")] = 0; // works for LF, CR, CRLF, LFCR, ...
تعتبر الوظيفة عدد الأحرف حتى تصل إلى أ '\r'
أو أ '\n'
(بمعنى آخر ، يجد الأول '\r'
أو '\n'
). إذا لم تصل إلى أي شيء ، فسيتوقف عند '\0'
(إرجاع طول السلسلة).
لاحظ أن هذا يعمل بشكل جيد حتى لو لم يكن هناك سطر جديد ، لأنه strcspn
يتوقف عند أ '\0'
. في هذه الحالة ، يتم استبدال الخط بأكمله ببساطة '\0'
مع '\0'
.
size_t ln = strlen(name) - 1;
if (*name && name[ln] == '\n')
name[ln] = '\0';
فيما يلي نهج سريع لإزالة الإمكانات '\n'
من سلسلة محفوظة بواسطة fgets()
.
يستخدم strlen()
, ، مع 2 اختبارات.
char buffer[100];
if (fgets(buffer, sizeof buffer, stdin) != NULL) {
size_t len = strlen(buffer);
if (len > 0 && buffer[len-1] == '\n') {
buffer[--len] = '\0';
}
استخدم الآن buffer
و len
كما هو مطلوب.
هذه الطريقة لها فائدة جانبية من len
قيمة الرمز اللاحق. يمكن أن يكون أسرع بسهولة من strchr(Name, '\n')
. المرجع YMMV ، ولكن كلتا الطريقتين تعمل.
buffer
, ، من الأصل fgets()
لن يحتوي في "\n"
في ظل بعض الظروف:
أ) كان الخط طويل جدا ل buffer
لذلك فقط char
قبل '\n'
يتم حفظه buffer
. تظل الشخصيات غير المقروءة في الدفق.
ب) لم ينتهي السطر الأخير في الملف بـ '\n'
.
إذا كان المدخلات قد تم تضمين أحرف فارغة '\0'
فيه في مكان ما ، الطول الذي أبلغ عنه strlen()
لن تشمل '\n'
موقعك.
بعض الإجابات الأخرى 'قضايا:
strtok(buffer, "\n");
فشل في إزالة'\n'
متىbuffer
هو"\n"
. من هذا إجابه - معدّل بعد هذه الإجابة لتحذير هذا القيد.فشل التالي في مناسبات نادرة عندما يكون الأول
char
اقرأ بواسطةfgets()
هو'\0'
. يحدث هذا عندما يبدأ الإدخال بتضمين'\0'
. ثمbuffer[len -1]
يصبحbuffer[SIZE_MAX]
الوصول إلى الذاكرة بالتأكيد خارج النطاق الشرعي لـbuffer
. شيء قد يحاول أو يجده القراصنة في قراءة ملفات UTF16 بحماقة. كانت هذه حالة إجابه عندما تمت كتابة هذه الإجابة. في وقت لاحق ، قام غير OP بتحريره لتضمين رمز مثل Check of This Found""
.size_t len = strlen(buffer); if (buffer[len - 1] == '\n') { // FAILS when len == 0 buffer[len -1] = '\0'; }
sprintf(buffer,"%s",buffer);
هو سلوك غير محدد: المرجع. علاوة على ذلك ، فإنه لا ينقذ أي مسافة بيضاء رائدة أو مفصولة أو زائدة. حاليا تم الحذف.تحرير بسبب الخير لاحقًا إجابه] لا توجد مشاكل مع 1 بطانة
buffer[strcspn(buffer, "\n")] = 0;
بخلاف الأداء مقارنة معstrlen()
يقترب. عادةً ما يكون الأداء في التشذيب ليس بمثابة رمز معين يقوم بإدخال/إخراج - ثقب أسود من وقت وحدة المعالجة المركزية. في حالة حاجة المدونة التالية إلى طول السلسلة أو يكون واعيًا للغاية للأداء ، استخدم هذاstrlen()
يقترب. آخرstrcspn()
هو بديل جيد.
مباشرة لإزالة ' n' من إخراج fgets إذا كان كل سطر لديه ' n'
line[strlen(line) - 1] = '\0';
خلاف ذلك:
void remove_newline_ch(char *line)
{
int new_line = strlen(line) -1;
if (line[new_line] == '\n')
line[new_line] = '\0';
}
لفرد ' n' trmming ،
void remove_new_line(char* string)
{
size_t length = strlen(string);
if((length > 0) && (string[length-1] == '\n'))
{
string[length-1] ='\0';
}
}
لتوفير متعددة ' n' ،
void remove_multi_new_line(char* string)
{
size_t length = strlen(string);
while((length>0) && (string[length-1] == '\n'))
{
--length;
string[length] ='\0';
}
}
تيم čas بطانة مدهشة بالنسبة للسلاسل التي تم الحصول عليها عن طريق مكالمة إلى FGTS ، لأنك تعلم أنها تحتوي على سطر جديد واحد في النهاية.
إذا كنت في سياق مختلف وترغب في التعامل مع السلاسل التي قد تحتوي على أكثر من سطر جديد ، فقد تبحث عن STRRSPN. إنه ليس Posix ، مما يعني أنك لن تجدها على جميع الوحدات. كتبت واحدة لاحتياجاتي الخاصة.
/* Returns the length of the segment leading to the last
characters of s in accept. */
size_t strrspn (const char *s, const char *accept)
{
const char *ch;
size_t len = strlen(s);
more:
if (len > 0) {
for (ch = accept ; *ch != 0 ; ch++) {
if (s[len - 1] == *ch) {
len--;
goto more;
}
}
}
return len;
}
بالنسبة لأولئك الذين يبحثون عن مكافئ perl chomp في C ، أعتقد أن هذا هو (Chomp يزيل فقط خط Newline Trailing).
line[strrspn(string, "\r\n")] = 0;
وظيفة STRRCSPN:
/* Returns the length of the segment leading to the last
character of reject in s. */
size_t strrcspn (const char *s, const char *reject)
{
const char *ch;
size_t len = strlen(s);
size_t origlen = len;
while (len > 0) {
for (ch = reject ; *ch != 0 ; ch++) {
if (s[len - 1] == *ch) {
return len;
}
}
len--;
}
return origlen;
}
إذا كنت تستخدم getline
هو خيار - لا تهمل مشكلات الأمان الخاصة بها ، وإذا كنت ترغب في استعداد المؤشرات - يمكنك تجنب وظائف السلسلة مثل getline
إرجاع عدد الأحرف. شيء مثل أدناه
#include<stdio.h>
#include<stdlib.h>
int main(){
char *fname,*lname;
size_t size=32,nchar; // Max size of strings and number of characters read
fname=malloc(size*sizeof *fname);
lname=malloc(size*sizeof *lname);
if(NULL == fname || NULL == lname){
printf("Error in memory allocation.");
exit(1);
}
printf("Enter first name ");
nchar=getline(&fname,&size,stdin);
if(nchar == -1){ // getline return -1 on failure to read a line.
printf("Line couldn't be read..");
// This if block could be repeated for next getline too
exit(1);
}
printf("Number of characters read :%zu\n",nchar);
fname[nchar-1]='\0';
printf("Enter last name ");
nchar=getline(&lname,&size,stdin);
printf("Number of characters read :%zu\n",nchar);
lname[nchar-1]='\0';
printf("Name entered %s %s\n",fname,lname);
return 0;
}
ملحوظة: ال [ قضايا الأمن ] مع getline
لا ينبغي إهمالها رغم ذلك.
طريقتي المبتدئ ؛-) يرجى إعلامي إذا كان هذا صحيحًا. يبدو أنه يعمل من أجل جميع حالاتي:
#define IPT_SIZE 5
int findNULL(char* arr)
{
for (int i = 0; i < strlen(arr); i++)
{
if (*(arr+i) == '\n')
{
return i;
}
}
return 0;
}
int main()
{
char *input = malloc(IPT_SIZE + 1 * sizeof(char)), buff;
int counter = 0;
//prompt user for the input:
printf("input string no longer than %i characters: ", IPT_SIZE);
do
{
fgets(input, 1000, stdin);
*(input + findNULL(input)) = '\0';
if (strlen(input) > IPT_SIZE)
{
printf("error! the given string is too large. try again...\n");
counter++;
}
//if the counter exceeds 3, exit the program (custom function):
errorMsgExit(counter, 3);
}
while (strlen(input) > IPT_SIZE);
//rest of the program follows
free(input)
return 0;
}
الوظيفة أدناه هي جزء من مكتبة معالجة السلسلة التي أحتفظ بها على Github. إنه يزيل وأحرف غير مرغوب فيه من سلسلة ، بالضبط ما تريده
int zstring_search_chr(const char *token,char s){
if (!token || s=='\0')
return 0;
for (;*token; token++)
if (*token == s)
return 1;
return 0;
}
char *zstring_remove_chr(char *str,const char *bad) {
char *src = str , *dst = str;
while(*src)
if(zstring_search_chr(bad,*src))
src++;
else
*dst++ = *src++; /* assign first, then incement */
*dst='\0';
return str;
}
يمكن أن يكون استخدام مثال
Example Usage
char s[]="this is a trial string to test the function.";
char const *d=" .";
printf("%s\n",zstring_remove_chr(s,d));
Example Output
thisisatrialstringtotestthefunction
قد ترغب في التحقق من الوظائف المتاحة الأخرى ، أو حتى المساهمة في المشروع :)https://github.com/fnoyanisi/zstring
for(int i = 0; i < strlen(Name); i++ )
{
if(Name[i] == '\n') Name[i] = '\0';
}
يجب عليك محاولة إعطائها. هذا الرمز بشكل أساسي من خلال السلسلة حتى يجد " n". عندما يتم العثور عليها ، سيتم استبدال " n" بمثبة الأحرف الخالية " 0"
لاحظ أنك تقارن الأحرف وليس السلاسل في هذا السطر ، فلا داعي لاستخدام STRCMP ():
if(Name[i] == '\n') Name[i] = '\0';
بما أنك ستستخدم عروض أسعار واحدة وليس عروض أسعار مزدوجة. هنا رابط حول عروض أسعار مزدوجة واحدة مقابل إذا كنت تريد معرفة المزيد
جرب هذه:
int remove_cr_lf(char *str)
{
int len =0;
len = strlen(str);
for(int i=0;i<5;i++)
{
if (len>0)
if (str[len-1] == '\n')
{
str[len-1] = 0;
len--;
}
if (len>0)
if (str[len-1] == '\r')
{
str[len-1] = 0;
len--;
}
}
return 0;
}