归一化之readline学习

本文详细介绍了fgets函数用于从文件或流中读取一行文本,以及strrchr函数用于在字符串中搜索特定字符。通过实例演示了如何使用这两个函数进行文本处理,并解释了它们的工作原理及参数意义。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

char* readline(FILE *input)
{
	int len;

	if(fgets(line,max_line_len,input) == NULL)
		return NULL;

	while(strrchr(line,'\n') == NULL)
	{
		max_line_len *= 2;
		line = (char *) realloc(line, max_line_len);
		len = (int) strlen(line);
		if(fgets(line+len,max_line_len-len,input) == NULL)
			break;
	}
	return line;
}

fgets函数解释:

从流中读一行或指定个字符, 原型是char *fgets(char *s, int n, FILE *stream);从流中读取n-1个字符,除非读完一行,参数s是来接收字符串,如果成功则返回s的指针,否则返回NULL。

  形参注释:*s结果数据的首地址;n-1:一次读入数据块的长度,其默认值为1k,即1024;stream文件指针

  例:如果一个文件的当前位置的文本如下

  Love ,I Have

  But ........

  如果用 

  fgets(str1,4,file1);

  则执行后str1="Lov",读取了4-1=3个字符,

  而如果用 

  fgets(str1,23,file1);

  则执行str1="Love ,I Have",读取了一行(包括行尾的'\n',并自动加上字符串结束符'\0')。

strrchr用法:

strrchr() 函数查找字符在指定字符串中从后面开始的第一次出现的位置,如果成功,则返回指向该位置的指针,如果失败,则返回 false。

语法

  strrchr(string,char)

using System; using System.Collections.Generic; using System.Linq; namespace LevelingAdjustment { class Program { static void Main(string[] args) { Console.WriteLine("四等水准路线平差计算程序"); Console.WriteLine("1. 闭合水准路线平差"); Console.WriteLine("2. 复合水准路线平差"); Console.Write("请选择计算类型(1/2): "); int choice = int.Parse(Console.ReadLine()); switch (choice) { case 1: ClosedLevelingAdjustment(); break; case 2: CompositeLevelingAdjustment(); break; default: Console.WriteLine("无效选择!"); break; } } // 闭合水准路线平差 static void ClosedLevelingAdjustment() { Console.WriteLine("\n闭合水准路线平差计算"); // 输入已知点高程 Console.Write("输入已知点A的高程(m): "); double knownElevation = double.Parse(Console.ReadLine()); // 输入测段数 Console.Write("输入测段数: "); int segmentCount = int.Parse(Console.ReadLine()); List<LevelingSegment> segments = new List<LevelingSegment>(); // 输入各测段数据 for (int i = 0; i < segmentCount; i++) { Console.WriteLine($"\n测段 {i + 1}:"); Console.Write($"输入点{i + 1}到点{i + 2}的观测高差(m): "); double deltaH = double.Parse(Console.ReadLine()); Console.Write($"输入点{i + 1}到点{i + 2}的距离(km): "); double distance = double.Parse(Console.ReadLine()); segments.Add(new LevelingSegment { FromPoint = $"P{i + 1}", ToPoint = $"P{i + 2}", ObservedDeltaH = deltaH, Distance = distance }); } // 计算闭合差 double totalObservedDeltaH = segments.Sum(s => s.ObservedDeltaH); double closureError = totalObservedDeltaH; Console.WriteLine($"\n闭合差: {closureError:F6} m"); // 计算允许闭合差 double totalDistance = segments.Sum(s => s.Distance); double allowedClosure = CalculateAllowedClosure(totalDistance, LevelingGrade.Fourth); Console.WriteLine($"允许闭合差: ±{allowedClosure:F6} m"); // 检查闭合差是否超限 if (Math.Abs(closureError) > allowedClosure) { Console.WriteLine("警告: 闭合差超限,需要重测!"); return; } // 计算平差 double correctionPerKm = -closureError / totalDistance; Console.WriteLine($"每公里改正数: {correctionPerKm:F8} m/km"); Console.WriteLine("\n平差计算结果:"); Console.WriteLine("点号\t高程(m)\t\t改正后高差(m)\t距离(km)"); double currentElevation = knownElevation; Console.WriteLine($"P1\t{currentElevation:F4}\t-\t\t-"); for (int i = 0; i < segments.Count; i++) { var segment = segments[i]; double correction = correctionPerKm * segment.Distance; double adjustedDeltaH = segment.ObservedDeltaH + correction; currentElevation += adjustedDeltaH; Console.WriteLine($"{segment.ToPoint}\t{currentElevation:F4}\t\t{adjustedDeltaH:F6}\t\t{segment.Distance:F2}"); } // 验证闭合差 double checkClosure = currentElevation - knownElevation; Console.WriteLine($"\n平差后闭合差: {checkClosure:F6} m"); } // 复合水准路线平差 static void CompositeLevelingAdjustment() { Console.WriteLine("\n复合水准路线平差计算"); // 输入已知点高程 Console.Write("输入已知点A的高程(m): "); double knownElevationA = double.Parse(Console.ReadLine()); Console.Write("输入已知点B的高程(m): "); double knownElevationB = double.Parse(Console.ReadLine()); // 输入测段数 Console.Write("输入测段数: "); int segmentCount = int.Parse(Console.ReadLine()); List<LevelingSegment> segments = new List<LevelingSegment>(); // 输入各测段数据 for (int i = 0; i < segmentCount; i++) { Console.WriteLine($"\n测段 {i + 1}:"); Console.Write($"输入起点: "); string fromPoint = Console.ReadLine(); Console.Write($"输入终点: "); string toPoint = Console.ReadLine(); Console.Write($"输入观测高差(m): "); double deltaH = double.Parse(Console.ReadLine()); Console.Write($"输入距离(km): "); double distance = double.Parse(Console.ReadLine()); segments.Add(new LevelingSegment { FromPoint = fromPoint, ToPoint = toPoint, ObservedDeltaH = deltaH, Distance = distance }); } // 构建邻接表 Dictionary<string, List<SegmentInfo>> adjacencyList = new Dictionary<string, List<SegmentInfo>>(); foreach (var segment in segments) { if (!adjacencyList.ContainsKey(segment.FromPoint)) { adjacencyList[segment.FromPoint] = new List<SegmentInfo>(); } adjacencyList[segment.FromPoint].Add(new SegmentInfo { ToPoint = segment.ToPoint, DeltaH = segment.ObservedDeltaH, Distance = segment.Distance }); // 添加反向边(用于后续处理) if (!adjacencyList.ContainsKey(segment.ToPoint)) { adjacencyList[segment.ToPoint] = new List<SegmentInfo>(); } adjacencyList[segment.ToPoint].Add(new SegmentInfo { ToPoint = segment.FromPoint, DeltaH = -segment.ObservedDeltaH, Distance = segment.Distance }); } // 计算各点近似高程 Dictionary<string, double> approximateElevations = new Dictionary<string, double>(); approximateElevations["A"] = knownElevationA; // 使用广度优先搜索计算近似高程 Queue<string> queue = new Queue<string>(); queue.Enqueue("A"); while (queue.Count > 0) { string currentPoint = queue.Dequeue(); if (adjacencyList.ContainsKey(currentPoint)) { foreach (var neighbor in adjacencyList[currentPoint]) { if (!approximateElevations.ContainsKey(neighbor.ToPoint)) { approximateElevations[neighbor.ToPoint] = approximateElevations[currentPoint] + neighbor.DeltaH; queue.Enqueue(neighbor.ToPoint); } } } } // 构建权逆阵和常数项 Dictionary<string, double> l = new Dictionary<string, double>(); Dictionary<string, double> v = new Dictionary<string, double>(); Dictionary<string, Dictionary<string, double>> p = new Dictionary<string, Dictionary<string, double>>(); // 初始化 foreach (var point in approximateElevations.Keys) { l[point] = 0; v[point] = 0; p[point] = new Dictionary<string, double>(); } // 设置已知点约束 p["A"]["A"] = 1; l["A"] = knownElevationA; p["B"]["B"] = 1; l["B"] = knownElevationB; // 构建法方程 foreach (var segment in segments) { string from = segment.FromPoint; string to = segment.ToPoint; double deltaH = segment.ObservedDeltaH; double distance = segment.Distance; double weight = 1 / distance; // 权与距离成反比 // 更新常数项 l[to] += weight * (approximateElevations[from] + deltaH); l[from] += weight * approximateElevations[to]; // 更新权逆阵 p[to][to] += weight; p[from][from] += weight; p[to][from] -= weight; p[from][to] -= weight; } // 高斯消元法解法方程 var points = p.Keys.ToList(); int n = points.Count; for (int i = 0; i < n; i++) { string pi = points[i]; // 主元归一化 double diag = p[pi][pi]; if (Math.Abs(diag) < 1e-10) { Console.WriteLine("矩阵奇异,无法求解!"); return; } for (int j = 0; j < n; j++) { string pj = points[j]; if (i == j) continue; double factor = p[pj][pi] / diag; // 消元 foreach (var k in p[pi].Keys.ToList()) { p[pj][k] -= factor * p[pi][k]; } l[pj] -= factor * l[pi]; } } // 回代求解 Dictionary<string, double> delta = new Dictionary<string, double>(); for (int i = n - 1; i >= 0; i--) { string pi = points[i]; delta[pi] = l[pi] / p[pi][pi]; } // 计算平差后高程 Dictionary<string, double> adjustedElevations = new Dictionary<string, double>(); foreach (var point in approximateElevations.Keys) { adjustedElevations[point] = approximateElevations[point] + delta[point]; } // 输出结果 Console.WriteLine("\n平差计算结果:"); Console.WriteLine("点号\t近似高程(m)\t改正数(m)\t平差后高程(m)"); foreach (var point in adjustedElevations.OrderBy(p => p.Key)) { Console.WriteLine($"{point.Key}\t{approximateElevations[point.Key]:F4}\t\t{delta[point.Key]:F6}\t\t{point.Value:F4}"); } // 计算单位权中误差 double vpv = 0; foreach (var segment in segments) { string from = segment.FromPoint; string to = segment.ToPoint; double observedH = segment.ObservedDeltaH; double adjustedH = adjustedElevations[to] - adjustedElevations[from]; double V = observedH - adjustedH; double weight = 1 / segment.Distance; vpv += V * V * weight; } double N = segments.Count; double f = n - (adjustedElevations.Count - 2); // 自由度 = 观测数 - 未知数(已知点不计) double sigma0 = Math.Sqrt(vpv / f); Console.WriteLine($"\n单位权中误差: {sigma0:F6} m"); Console.WriteLine($"自由度: {f}"); } // 计算允许闭合差 static double CalculateAllowedClosure(double totalDistance, LevelingGrade grade) { switch (grade) { case LevelingGrade.Fourth: return 6 * Math.Sqrt(totalDistance); // 四等水准允许闭合差 case LevelingGrade.Third: return 12 * Math.Sqrt(totalDistance); // 三等水准允许闭合差 default: return 6 * Math.Sqrt(totalDistance); } } } // 测段类 class LevelingSegment { public string FromPoint { get; set; } public string ToPoint { get; set; } public double ObservedDeltaH { get; set; } // 观测高差 public double Distance { get; set; } // 距离(km) } // 邻接表信息类 class SegmentInfo { public string ToPoint { get; set; } public double DeltaH { get; set; } public double Distance { get; set; } } // 水准等级枚举 enum LevelingGrade { Fourth, Third } }
06-03
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值