我有一个坐标对的输入文件(比方说10行),每行看起来像这样:
(1653408W,503223N)(1651614W,502806N)
我试图将给定的输入放入DMS格式。输入文件中的每一行以\n
字符结尾,我想循环遍历文件并在最终的\n
之后停止。我在考虑使用类似的东西:
while(fscanf(filename,
"(%3d%2d%2d%c, %2d%2d%2d%c) (%3d%2d%2d%c, %2d%2d%2d%c)\n",
&firstLonD, &firstLonM, &firstLonS, &firstLonC,
&firstLatD, &firstLatM, &firstLatS, &firstLatC,
&secLonD, &secLonM. &secLonS, &secLonC,
&secLatD, &secLatM, &secLatS, &secLatC) == 16) {
//do something
}
很抱歉长循环条件和可能的可读性差。有关如何进行的任何建议?
fscanf格式字符串中的空格和换行符与输入中的空格和换行符不匹配。相反,格式中的任何空格字符意味着“跳过空格”,读取和丢弃空格,直到找到任何非空白字符 - 这可能是下一个字符,因此不会跳过任何内容。此外,大多数转换说明符也会跳过空格,因此您只需要格式字符或%c
,%[
和%n
directives之前格式的空格,这些空格不会跳过空格。
因此,为了您的目的,您需要一个格式字符串,如:
while(fscanf(filename,
" (%3d%2d%2d%c ,%2d%2d%2d%c ) (%3d%2d%2d%c ,%2d%2d%2d%c )",
&firstLonD, &firstLonM, &firstLonS, &firstLonC,
&firstLatD, &firstLatM, &firstLatS, &firstLatC,
&secLonD, &secLonM. &secLonS, &secLonC,
&secLatD, &secLatM, &secLatS, &secLatC) == 16) {
虽然在循环中读取单个坐标也可能更好,但稍后将它们配对:
while(fscanf(filename,
" (%3d%2d%2d%c ,%2d%2d%2d%c )",
&LonD, &LonM, &LonS, &LonC,
&LatD, &LatM, &LatS, &LatC) == 8) {
将纬度/经度读作单个数字然后将div / mod分为100度的度/分/秒也可能更好:
while(fscanf(file, " (%d%c ,%d%c )", &lonVal, &lonDir, &latVal, &latDir) == 4) {
lonDeg = lonVal / 10000;
lonMin = (lonVal % 10000) / 100;
lonSec = lonVal % 100;
通过这种方式,你可以处理<100度的经度而不需要领先0来使它们正好是7位数......
关于scanf和朋友的事情是他们想要阅读由空格分隔的内容,他们真的不在乎它是什么样的空白。因此,只用空格(或制表符)输入所有一行就像多行一样“相同”。这是scanf工作方式的有意“特征”,因此如果您真正关心换行符和其他空格之间的区别,则scanf不是正确的工具。
#include <stdlib.h>
File *file;
size_t len = 0;
ssize_t read;
char * line = NULL;
while ((read = getline(&line, &len, file)) != -1)
{
printf("%s",line);
if(sscanf(line, "....format",...)==16)){
..............
}
}
更好的设计是从具有直接字符串读取功能的文件(如fgets
)中读取行,然后对使用sscanf
或类似文件从文件读取的字符串使用字符串解析。 scanf
-family函数通常不应该用于直接从流中读取,只能从字符串中读取。
然后,您还应检查sscanf
的返回值,以确保每个值都被适当地扫描到预期类型。
char line[200];
while(fgets(line, 200, stdin))
{
if(sscanf(line, "<format-string-here>", ...) != 16)
{
// handle error
}
}